Ci使用HMVC时增加查询缓存
如果你有扩展过CI的HMVC(hex提供的方案),你可能会在实际使用的过程中越来越理解HMVC,但也可能会越来越搞不清楚什么是HMVC,正如paperen一样…有时候特别觉得模块这个词实在是抽象,到底什么才能定义为模块,到底概念并不是最重要,重要的是你用起来是否合理,是否有效,是否能更好减少耦合。
在paperen使用hex提供的这个hmvc方案过程中,确实也遇到了一些bug,不过目前的已经得到修复,关于hmvc我觉得重要一点是模块之间数据不能共用,而导致一个页面有可能执行了多条一样的SQL,想体现一下这种现象,也很简单。
这是原始调用模型的写法
$this->load->model('userlog_model'); print_r( $this->userlog_model->all() );
调用了userlog_model中的all方法,是什么不要紧,反正你知道这里就是送出一条SQL就够了
而假设我们有两个模块test3,test4,调用各自的test方法都会调用这个模型的这个all方法,现在我在welcome控制器的test方法里面写下这两段,分别调用test3、test4模块的test方法
并输出调试数据
$this->output->enable_profiler();
那么访问该URL后你会看到调试数据
执行了两条一样的sql,当然因为mysql自身有缓存机制所以第二条sql花费的时间小一点,但是毕竟送出两条SQL始终会增加程序等待数据库数据响应的时间,而且说实在其实数据是可以公用的,我们只需要建立一种机制就可以实现,paperen这里直接放出自己这个方案好了,就是引入了一个叫querycache的类,调用模型的方法时也不像原始那样写了
下面是一个使用范例
// querycache print_r( $this->querycache->get( 'userlog', 'all' ) );就是这样就已经可以了,不妨对比一下上面的原始写法,使用querycache就更加懒了,不用每次都$this->load->model,querycache会自动给你加载相关的模型
以下为querycache的代码
<?php /** * 作為查詢緩存,避免不同模塊執行相同SQL導致性能下降一個組件 * 依賴于CI模型 * @author paperen */ class Querycache { private $_CI; private $_cache; function __construct() { $this->_CI = & get_instance(); } /** * 直接執行模型操作 * @param string $model_name 模型名 * @param string $method 方法 * @param mixed $args 參數 * @return mixed */ public function execute( $model, $method, $args ) { $model_name = "{$model}_model"; if ( !isset( $this->_CI->$model_name ) ) $this->_CI->load->model( $model_name ); return call_user_func_array( array( $this->_CI->$model_name, $method ), $args ); } /** * * @param string $model 模型名(不需要加_model) * @param string $method 方法 * @return mixed */ public function get( $model, $method ) { // 获取参数数据 $args = func_get_args(); $model_and_method = array_shift( $args ) . '_' . array_shift( $args ); // 索引 $hash = "{$model_and_method}_" . serialize( $args ); // 存在缓存直接返回 if ( isset( $this->_cache[$hash] ) ) return $this->_cache[$hash]; // 通过模型获取数据 $result = $this->execute( $model, $method, $args, TRUE ); // 缓存起来 $this->_cache[$hash] = $result; return $result; } } // end of Querycache
就是有execute与get两个public的方法,只有使用get才具有查询缓存概念,而execute一般是使用在insert与update的操作,因为更新与插入并不需要缓存起来,只有查询才需要,当将test3、test4模块中的test方法中的查询都改为使用querycache的话,你会看到这个页面只执行了一条SQL
这就是我们想要的效果,不同模块中调用相同模型相同方法相同参数时,就不用重复送同样的SQL了,若曾经执行过的话直接将数据返回就可以了
若模型的方法有多个参数,比如以下这个方法
function all( $per_page = 5, $offset = 0 ) { print_r( func_get_args() ); return $this->db->from('userlog')->get()->result_array(); }
那么你的get这样写就可以了
// querycache arguments print_r( $this->querycache->get( 'userlog', 'all', 7, 3 ) );
有更多参数就在get中加,参数从三个起顺序与模型相应的方法顺序一致即可
关于插入与更新时即调用execute方法
// insert or update $insert_data = array( 'recordtime' => time(), 'action' => 'do something', 'userid' => 5, ); $this->querycache->execute( 'userlog', 'insert', array( $insert_data ) );
第三个参数必需是数组(用array包起来),如果有多个参数则array( $arg1, $arg2 ),顺序与模型对应方法顺序一致
function insert( $arg1, $arg2 ) { print_r( func_get_args() ); }
好吧,希望这个能帮到你,good night~~
評論
0沒有任何評論