ThinkPHP 模板解析流程,研究笔记。

论坛 期权论坛 脚本     
已经匿名di用户   2022-5-29 19:29   1367   0
ThinkPHP 控制器-方法中,通过
$this->display();

来输出带有模板的视图。

那么就从这个方法入手。

1.Action.class.php 控制器基类

这是控制器基类,在这里面找到display()方法。

    protected function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
        $this->view->display($templateFile,$charset,$contentType,$content,$prefix);
    }


可以看出,这里实际上是调用 View视图类的display()方法。


2.View.class.php 视图类

public function display($templateFile='',$charset='',$contentType='',$content='',$prefix='') {
        ...
        // 解析并获取模板内容
        $content = $this->fetch($templateFile,$content,$prefix);
        // 输出模板内容
        $this->render($content,$charset,$contentType);
        ...
}

关键在于fetch()方法和render()方法,其他的不管。

public function fetch($templateFile='',$content='',$prefix='') {
        ...//没有指定模板文件的话,自动定位模板文件,省略
        // 页面缓存
        ob_start();
        ob_implicit_flush(0);
        if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
            // 模板阵列变量分解成为独立变量
            extract($this->tVar, EXTR_OVERWRITE);
            // 直接载入PHP模板
            empty($content)?include $templateFile:eval('?>'.$content);
        }else{
            // 视图解析标签
            $params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
            tag('view_parse',$params);
        }
        // 获取并清空缓存
        $content = ob_get_clean();
        // 内容过滤标签
        tag('view_filter',$content);
        // 输出模板文件
        return $content;
    }
简单解释下 $this->tVar 是一个数组,当你$this->assign('a','b')的时候,就会自动添加$this->tVar['a']='b',然后通过extract()函数将数组转化为独立变量,即$a='b';这只在PHP原生模板时生效,而我们常规情况下是 else{ 之后的过程,也就是

$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
tag('view_parse',$params);

这两行代码,$params是将一些变量组成一个数组,通过tag调用view_parse处的行为(在conf/tags.php中定义),该行为类是lib/behavior/ParseTemplateBehavior.class.php;

这个行为来解析视图标签。


3.ParseTemplateBehavior 模板解析核心行为

行为通过run()方法开始解析,而上面的$params作为引用参数传递到run(&$_data)中。即$_data=&$params,下面从run()方法分析。
篇幅关系,这里就不打代码了。

大致流程如下:

检测模板缓存文件是否存在并且有效,存在的话直接include它,如果不存在,则调用ThinkTemplate类下的fetch方法进行模板解析和编译,将编译结果写入缓存,并include缓存文件。

缓存文件就是将模板进行标签替换后的一个PHP脚本,include它的话就是输出页面了。


4. 模板的编译

模板编译函数位于ThinkTemplate.class.php中,方法是:protected function compiler($tmplContent){} 只有一个参数,就是读取模板文件的内容字符串。

protected function compiler($tmplContent) {
        //模板解析
        $tmplContent =  $this->parse($tmplContent);
        // 还原被替换的Literal标签
        $tmplContent =  preg_replace('/<!--###literal(\d+)###-->/eis',"\$this->restoreLiteral('\\1')",$tmplContent);
        // 添加安全代码
        $tmplContent =  '<?php if (!defined(\'THINK_PATH\')) exit();?>'.$tmplContent;
        if(C('TMPL_STRIP_SPACE')) {
            /* 去除html空格与换行 */
            $find           = array('~>\s+<~','~>(\s+\n|\r)~');
            $replace        = array('><','>');
            $tmplContent    = preg_replace($find, $replace, $tmplContent);
        }
        // 优化生成的php代码
        $tmplContent = str_replace('?><?php','',$tmplContent);
        return strip_whitespace($tmplContent);
    }

调用parse方法解析模板:

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:81
帖子:4969
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP