原创作者: vb2005xu
阅读:1048次
评论:0条
更新时间:2011-05-26
xser php5 framework v0.11 测试版 新增的功能 对于视图缓存控制的处理,轻松设置就能实现功能强大的缓存功能. 颗粒度细分到action,对不同的udi资源[命名空间::控制器/action@模块] 能自定义缓存文件路径信息设置 1. config/html-cache-rules.php // 缓存策略设置文件 遵循udi_string格式 return array( //=> welcome.html , welcome.html.asc 'default::application/index@default' => 'default/welcome.html' , 'default::application/show@default' => 'default/application/show/{name}-{book_id}.html' , ); 其中 花括号包含的是 可变量,他们由前端$_GET数组中的值来替换.缓存文件对应到 cache/_app/ 这个目录 比如: index.php?e=show&name=xx&book_id=112 对应于 cache/_app/default/application/show/xx-112.html 2. 控制器设置,要启用缓存功能,不用担心要写很多辅助代码,只需重写以下方法 protected function _before_execute($action_method){ $this->enable_cache = true ; // 将这行加入其中即可 } 例如: application 控制器为默认控制器, 在 config/boot.php中进行了设置: 'default_controller' => 'application', class application_controller extends xser_controller { function actionIndex(){ $this->_view['current_uri'] = 'index.php?q=application&e=index' ; } function actionShow(){ $this->_view['name'] = $_GET['name'] ; $this->_view['book_id'] = $_GET['book_id'] ; $this->_view['current_uri'] = 'index.php?q=application&e=show' ; } protected function _before_execute($action_method){ $this->enable_cache = true ; } } default::application/index@default 对应的视图文件如下: view/default/application/index.rhtml <?php $this->_block('contents'); ?> <h3><?php echo $current_uri ;?></h3> <?php $this->_endblock(); ?> <?php $this->_element('test'); ?> default::application/show@default 对应的视图文件如下: view/default/application/show.rhtml <?php $this->_block('contents'); ?> <h3><?php echo $name . ' -- ' . $book_id;?></h3> <?php $this->_endblock(); ?> <?php $this->_element('test'); ?> default::application@default 对应的元素 test的内容如下: view/default/_elements/test.rhtml <h2>This is a element file2 !</h2> index.php?e=show&name=xx&book_id=112 生成的缓存文件如下: cache/_app/default/application/show/xx-112.html <h3>xx -- 112</h3> <h2>This is a element file2 !</h2> index.php 生成的缓存文件如下: cache/_app/default/welcome.html <h3>index.php?q=application&e=index</h3> <h2>This is a element file2 !</h2> 3. 缓存更新的策略: 大家应该知道缓存文件的更新很多框架并没有具体实现,像smarty虽然提供了,但是对于局部更新 似乎并不简单,这里色色基本实现了缓存自动更新的一种简单方式... /** * 缓存更新的条件: * 1. 模板文件发生了改变: 里面引用的模板文件发生变化 * [布局模板文件,视图模板文件,元素模板文件]被更新 * * 2. 内容发生了更新 * [修改对应的数据缓存属性文件的时间戳] * * 每个缓存对应着两个文件: 数据缓存文件[xx.html],数据缓存属性文件[xx.html.asc] * * 缓存文件名模板: ns/mod/q/e/{name}.html => /admin/sys/user/show/lily.html */ class xser_html_cache 缓存具体都由这个类来处理,提供了三个公共方法 public function get_cache_content($udi_string,$cache_tplname_vars) public function cache_had_expired($udi_string,$cache_tplname_vars) public function put_cache_content($udi_string,$cache_tplname_vars,$cache_prop,$cache_content) 此类在框架中是一个单态形式的,使用前必须定义缓存策略设置文件config/html-cache-rules.php 这 三个方法 除了 cache_had_expired 这个提供给用户使用外,其它2个均由框架自身使用. cache_had_expired 方法用于应对第二个缓存更新的条件: 内容发生了更新 比如 咱在后台更新了 index.php?e=show&name=xx&book_id=112 它对应的数据内容,简单调用此方法即可,例如: 在 上文中提到的 application_controller protected function actionq(){ // 数据更新操作 // 设置缓存过期 xser::singleton('xser_html_cache') ->cache_had_expired('default::application/show@default',array( 'name' => 'xx' , 'book_id' => '112' , )); } 4. 对控制器的缓存功能的扩展,比如定义 控制器中 某些action才享有缓存功能,可以如下设置 protected function _before_execute($action_method){ $enable_cache_actions = array('index','show'); if (in_array($action_method,$enable_cache_actions)) $this->enable_cache = true ; } 5. 所有这一切都是在xser_controller这个控制器的基类中实现的,代码并未加多少,整个类的代码才136行,包含空行和注释 protected $enable_cache = false ; //新增变量 public function execute($action_name,xser_udi_object $udi){ $action_method = "action{$action_name}"; if ($this->method_exists($action_method)){ $this->udi = $udi ; // 调用 _before_execute() 方法 $this->_before_execute($action_method); // 缓存存在,直接取出缓存 if ($this->enable_cache){ $cache_content = $this->get_cache_content(); if ($cache_content != false ){ return $cache_content ; } // xser::dump($cache_content,'why?'); unset($cache_content); xser::replaceIni('__html_cache_tplname_vars#'.$udi->to_string(),$_GET); } // 执行 action 方法 $ret = $this->{$action_method}(); // 调用 _after_execute() 方法 $this->_after_execute($ret); if ($this->is_render()){ // 加载视图组件,进行渲染操作 xser::loadlibrary($this->_view_engine,'xser'); $view_class = "xser_{$this->_view_engine}" ; $view_render = new $view_class($this->udi); $view_render->assign($this->_view); //渲染之前执行 $this->_before_render($view_render); // 启用缓存,但缓存不存在,在视图组件中生成缓存 return $view_render->execute($this->enable_cache); } }else { $notice = sprintf('Action "%s" not defined in "%s".', $action_name,$udi['mapping_info']['controller_file'].'#'.get_class($this)); echo $notice ; Xser::log_provider()->exception($notice); // throw new Exception($notice); } return null; } // 缓存扩展 protected function get_cache_content(){ xser::loadlibrary('html_cache','xser'); return xser::singleton('xser_html_cache')->get_cache_content( $this->udi->to_string(),$_GET ) ; } 6. 视图引擎组件也相应的做了些改变 class xser_view // 新增变量 protected $_enable_cache = false ; //启用缓存 protected $udi_string = null ; protected function reinit(xser_udi_object $udi){ $this->udi_mapping_info = $udi->mapping_info() ; $this->udi_string = $udi->to_string(); $this->_vars = array( 'base_uri' => xser::ini('base_uri'), ); } public function execute($enable_cache=false){ $this->_enable_cache = $enable_cache ; $this->display(); } function fetch() { $this->_before_render(); $filename = Xser::ini('application_dir') ."/{$this->udi_mapping_info['view_action_file']}"; if (file_exists($filename)) { $view_parse = new xser_view_parse($this->_vars); $output = $view_parse->reset_ref_tpls()->parse($this->udi_mapping_info['view_action_file']); if ($this->_enable_cache){ // 新增代码 //引用的模板列表属性设置 $ref_tpls_prop = $view_parse->get_ref_tpls(); if (!empty($ref_tpls_prop)){ if (!class_exists('xser_html_cache')) xser::loadlibrary('html_cache','xser'); $cache_tplname_vars = xser::ini("__html_cache_tplname_vars#{$this->udi_string}",$_GET); xser::cleanIni("__html_cache_tplname_vars#{$this->udi_string}"); xser::singleton('xser_html_cache') ->put_cache_content($this->udi_string,$cache_tplname_vars,$ref_tpls_prop,$output); } } } else { $notice = "view file not exist: [{$this->udi_mapping_info['view_action_file']}]" ; echo $notice ; Xser::log_provider()->exception($notice); return ; // throw new Exception($notice); $output = ''; } $this->_after_render($output); return $output; } 7. class xser_view_parse 的变化 protected $_ref_tpls = array() ; public function get_ref_tpls(){ // 获取引用的模板文件 return $this->_ref_tpls ; } /** * @return xser_view_parse */ public function reset_ref_tpls(){ $this->_ref_tpls = array(); return $this ; } /** * 载入视图文件 */ protected function _include($___tpl, array $___vars = null) { $file = Xser::ini('application_dir') . "/{$___tpl}" ; if (!file_exists($file)){ $notice = "view file1 not exist: [{$___tpl}]" ; Xser::log_provider()->exception($notice); echo $notice ; return ; // throw new Exception($notice); } $this->_ref_tpls[$___tpl] = filemtime($file) ; extract($this->_vars); if (is_array($___vars)) extract($___vars); include $file; }
评论 共 0 条 请登录后发表评论