让thinkphp完美支持smarty模板


一,去掉了系统自带的think 模板引擎,用功能强大的smarty替代之,基本上可以说是完美支持smarty模板了。
原有的smarty模板接口只能实现基本的功能,比如判断模板是否已经缓存就无能为力,这样使用无疑大大削减了smarty的功能。
二,去掉了分组功能
三,默认使用php模板
四,支持带路由的dispatch
五,支持CURD方法、连贯操作、统计查询等
六,支持语言包、模板主题
七、去掉了大部分扩展机制
八、完美支持smarty模板引擎(ThinkPHP\Vendor\Smarty)

默认加载 :

convention.php
defines.php
functions.php
paths.php
runtime.php //生成核心和应用缓存用
core.php //include 文件用
alias.php //include 文件用
THinkphp/Lib/Think/Core
Log.class.php
Think.class.php
Db.class.php
Model.class.php
App.class.php
View.class.php
Action.class.php
Dispatcher.class.php

ThinkPHP\Lib\Think\Exception\ThinkException.class.php

THinkphp/Lib/Think/Util/
Debug.class.php
Session.class.php

可通过如下配置使用smarty模板引擎:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    /* 模板引擎设置 */
    'TMPL_ENGINE_TYPE'      => 'Smarty',  
    'TMPL_TEMPLATE_SUFFIX'  => '.html',     // 默认模板文件后缀
    'TMPL_CACHFILE_SUFFIX'  => '.php',      // 默认模板缓存后缀
    'TMPL_PARSE_STRING'     => array('__UPLOAD__'=>__ROOT__.'/Content/',), // 模板引擎要自动替换的字符串,必须是数组形式。
    'TMPL_ENGINE_CONFIG' => array(
              'debugging'=>true,
        //    'error_reporting'=>'',
        //    'exception_handler'=>array('ExceptionClass','ExceptionMethod'),  
             'template_dir' => TMPL_PATH,  //模板目录
              'compile_dir' =>TEMP_PATH ,//编译目录
              'cache_dir' =>CACHE_PATH,  //缓存目录
              'caching' => false,  //是否启用缓存
              'cache_lifetime' =>60*60*24,//缓存时间s
              'left_delimiter'=>'<{',
              'right_delimiter' =>'}>',
      )  ,
     'TMPL_ENGINE_SMARTY_FILTER'=>array(
          'output'=>'trimwhitespace',

          ),

这里初定义了smarty的编译目录、缓存目录、是否启用缓存、缓存时间、以及左定界符和右定界符,还有smarty的filter插件。(此处的trimwithespace用于过滤输出的html代码的空白。)
由于是开发时期,所以我还开启了smarty 的debugging(注意,由于修改了左右定界符,所以smarty的debugging模板也要作相应修改)。

关于 thinkphp的视图类(view)
thinkphp的视图类(view)是在核心库文件Action.class.php中__construct的实例化的,此__construct同时执行_initialize方法。
Action.class.php中的display方法是用于调用模板引擎的显示方法的,此处即为smarty的显示方法。为了让ThinkPHP支持Smarty的fetch方法和display方法的cache_id,让thinkphp里面调用display和fetch就像用smarty时一模一样,因此必须修改thinkphp
Action.class.php中的:
protected function display
protected function fetch
我还增加了几个方法(都是smarty里面的):
protected function is_cached
protected function clear_cache
具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    protected function display($templateFile='',$cache_id = null,$compile_id=null,$charset='',$contentType='text/html')
    {
        $this->view->display($templateFile,$cache_id,$compile_id,$charset,$contentType);
    }

 
    protected function fetch($templateFile='',$cache_id = null,$compile_id=null,$charset='',$contentType='text/html')
    {
        return $this->view->fetch($templateFile,$cache_id ,$compile_id,$charset,$contentType);
    }

  //判断模板文件是否已经被缓存
   //如果不是检查当前模块的操作模板,参数请用 module:action  方式
    protected function is_cached($template, $cache_id = null, $compile_id = null)
    {
        if(!file_exists_case($template))
           // 自动定位模板文件
            $template   = $this->view->parseTemplateFile($template);
        $template=substr($template,strlen(TMPL_PATH));
        return $this->view->smarty->is_cached($template, $cache_id, $compile_id);
    }
   
    //清除单一模板文件的缓存
    //如果不是清除当前模块的操作模板,参数请用 module:action  方式
    protected function clear_cache($template_name, $cache_id=null, $compile_id=null, $exp_time=null)
    {
            if(!file_exists_case($template_name))
           // 自动定位模板文件
            $template_name  = $this->view->parseTemplateFile($template_name);
        $template_name=substr($template_name,strlen(TMPL_PATH));
        return $this->view->smarty->clear_cache($template_name, $cache_id, $compile_id, $exp_time);
    }
   
    //清除所有smarty 静态缓存
    //返回清除的缓存数量
    protected function clear_all_cache($exp_time=null)
    {
        return $this->view->smarty->clear_all_cache($exp_time);
    }
   
   
    //清除smarty编译缓存
    //如果不带参数默认返回清除的编译缓存数量,带参数返回
    //如果不是清除当前模块的操作模板,参数请用 module:action  方式
        protected function clear_compiled_tpl($template_name=null)
    {
        if(null!=$template_name)
        {
        if(!file_exists_case($template_name))
         // 自动定位模板文件
            $template_name  = $this->view->parseTemplateFile($template_name);
        $template_name=substr($template_name,strlen(TMPL_PATH));
        }
        return $this->view->smarty->clear_compiled_tpl($template_name);
    }

这里注意,除了is_cached方法,其它的像clear_cache等我额外增加了函数如果在后调用并不会清除前台的缓存,除非前台后台是同一个app 。

进阶:让ThinkPHP支持Smarty的fetch方法的cache_id
这样以后肯定不行,还要修改Lib/Think/Core/View.class.php
增加一个属性,以支持调用插件:

1
2
3
4
    protected $cache_id=null;  //cache_id
    protected $compile_id=null;  //cache_id
    protected $smarty=null;
    public $filters=null;

构造函数修改成如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    function __construct()
    {
        $this->filters=C('FILTERS');
        $engine  = strtolower(C('TMPL_ENGINE_TYPE'));
        if('smarty'==$engine)
        {
            vendor('Smarty.Smarty#class');
            $tpl = new Smarty();
            if(C('TMPL_ENGINE_CONFIG'))
            {
                $config  =  C('TMPL_ENGINE_CONFIG');
                foreach ($config as $key=>$val)
                {
                    $tpl->{$key}   =  $val;
                }
            }
                else
            {
            $tpl->caching = C('TMPL_CACHE_ON');
            $tpl->template_dir = TMPL_PATH;
            $tpl->compile_dir = CACHE_PATH ;
            $tpl->cache_dir = TEMP_PATH ;
            }
            if(C('TMPL_ENGINE_SMARTY_FILTER'))
            {
                $filter  =  C('TMPL_ENGINE_SMARTY_FILTER');
                foreach ($filter as $key=>$val)
                {
                     $tpl->load_filter($key,$val);
                }
            }
       
        $this->smarty=&$tpl;
        }  
    }

其中FILTERS是配置文件中定义的,类型为一维数组。
例如在应用的配置文件中:

1
'FILTERS'=>array('hl_before_highlight_codeblock','hl_replace_attach_tag','hl_after_highlight_codeblock',),

其中的hl_before_highlight_codeblock等函数是在应用的Common/common.php文件中定义的,因为应用在编译时首先会包含应用目录下的Common/common.php 。
display方法修改成如下:

1
2
3
4
    public function display($templateFile='',$cache_id,$compile_id,$charset='',$contentType='text/html')
    {
        $this->fetch($templateFile,$cache_id,$compile_id,$charset,$contentType,true);
    }

fetch方法修改成如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  /**
     +----------------------------------------------------------
     * 加载模板和页面输出
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     * @param string $templateFile 模板文件名 留空为自动获取
     * @param string $charset 模板输出字符集
     * @param string $contentType 输出类型
     * @param string $display 是否直接显示
     +----------------------------------------------------------
     * @return mixed
     +----------------------------------------------------------
     */

    public function fetch($templateFile='',$cache_id=null,$compile_id=null,$charset='',$contentType='text/html',$display=false)
    {
        $GLOBALS['_viewStartTime'] = microtime(TRUE);
        if(null===$templateFile)
            // 使用null参数作为模版名直接返回不做任何输出
            return ;
        if(empty($charset))  $charset = C('DEFAULT_CHARSET');
        // 网页字符编码
        header("Content-Type:".$contentType."; charset=".$charset);
        header("Cache-control: private");  //支持页面回跳
        //页面缓存
        ob_start();
        ob_implicit_flush(0);

        if(!file_exists_case($templateFile))
            // 自动定位模板文件
            $templateFile   = $this->parseTemplateFile($templateFile);
 
        $engine  = strtolower(C('TMPL_ENGINE_TYPE'));
        if('php'==$engine)
        {
            // 模板阵列变量分解成为独立变量
            extract($this->tVar, EXTR_OVERWRITE);
            // 直接载入PHP模板
            include $templateFile;
        }
        else
        {
        // 调用 smarty
        // 调用模板引擎解析和输出
        $templateFile=substr($templateFile,strlen(TMPL_PATH));
        $this->smarty->assign($this->tVar);
        $this->smarty->display($templateFile,$cache_id,$compile_id);
        }
           
        $this->templateFile   =  $templateFile;
        $cache_id && $this->cache_id=$cache_id;  //存储cache_id ,荒野无灯添加
        $compile_id && $this->compile_id=$compile_id;  //存储cache_id ,荒野无灯添加
        // 获取并清空缓存
        $content = ob_get_clean();
        // 模板内容替换
        $content = $this->templateContentReplace($content);
            if(null!=$this->filters && is_array($this->filters))
        {
            $filterArray=$this->filters;
            for($i=0;$i<count($filterArray);$i++)
            {
                $content=call_user_func($filterArray[$i],$content);
                //array_shift($filterArray);
            }
        }
        // 输出模板文件
        return $this->output($content,$display);
    }

喜欢这篇文章吗?

请订阅本站 RSS feed填写您的邮件地址,订阅我们的精彩内容:

相关日志

回复 (6)

  1. 跑步鞋迷  / 回复

    我把配置文件里面设置过滤函数的那一行去掉就行了。
    但是一进后台要登陆的时候会出现这样的错误:
    Fatal error: Call to a member function assign() on a non-object in C:\Program Files\VertrigoServ\www\mpx\ThinkPHP\Lib\Think\Core\View.class.php on line 237

  2. 跑步鞋迷  / 回复

    ‘FILTERS’=>array(‘hl_before_highlight_codeblock’,'hl_replace_attach_tag’,'hl_after_highlight_codeblock’,)
    这三个函数在哪?没看到。。。要自己写吗

  3. jankuo  / 回复

    这个是2.0的还是?我也想用smarty但是又不想带太多的复杂文件,如果修改版本不是最新的,回复我下

发表评论 修改评论取消编辑

允许使用的标签 - 您可以在评论中使用如下的 HTML 标签以及属性。

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 :wink:  :-|  :-x  :twisted:  :)  8-O  :(  :roll:  :-P  :oops:  :-o  :mrgreen:  :lol:  :idea:  :-D  :evil:  :cry:  8)  :arrow:  :-?  :?:  :!:

引用通告 (0)

› 尚无引用通告。

开灯
如无法留言,请刷尝试新一下页面~~祝您春节愉快!
×