原创作者: 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 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

文章信息

  • vb2005xu在2010-04-03创建
  • vb2005xu在2011-05-26更新
  • 标签: php5, fr
Global site tag (gtag.js) - Google Analytics