一个迷你版Smarty模板引擎,认识模板引擎原理(附代码)

  前些时间在看创智博客韩顺平的Smarty模板引擎教程,再结合自己跟李炎恢第二季开发中CMS系统写的tpl模板引擎。今天就写一个迷你版的Smarty引擎,虽然说我并没有深入分析过Smarty的源码,但是对模板引擎的原理,还是有深刻的理解的。如果有什么还需要改进的地方,记得提出来。

  一、什么是Smarty模板引擎:

  Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目的就是要使PHP程序员同前端人员分离,使程序员改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。(来自百度百科)

  自己的理解是:

  第一,有利于把前端开发与后台开发工作分离,利于分工合作;

  第二,其缓存机制,有利于加快网站的访问速度;

  第三,模板标签还可以一次编写,到处调用,便利和简洁性好;

  二、下面就一起开发迷你版模板引擎吧

  (1)首先先把已经做好的模板引擎给大家看一看,先使用,再开发

  ①迷你版Smarty模板引擎目录结构如下:

  源代码里面有很详细的说明,请看下面

  ①要开发一个模板引擎,最主要的有两个类,分别是模板引擎入口类和模板解析类。

  A.首先创建MiniSmarty目录,然后新建一个文件名为MiniSmarty.class.php

  其代码如下:

/**
 * MiniSmarty模板引擎
 * @link http://www.cnblogs.com/isuhua/
 * @author 华仔_suhua <weibo.com/suhua123>
 * @package MiniSmarty
 * @version 0.0.0.1
 */
class MiniSmarty {
    //模板文件
    public $template_dir = 'templates';
    //编译文件
    public $compile_dir = 'templates_c';
    //缓存文件
    public $cache_dir = 'cache';
    //模板变量
    public $_tpl_var = array();
    //是否开启缓存
    public $caching = false;
    
    public function __construct() {
        $this->checkDir();
    }
    
    //检查目录是否建好
    private function checkDir() {
        if (!is_dir($this->template_dir)) {
            exit('模板文件目录templates不存在!请手动创建');
        }
        if (!is_dir($this->compile_dir)) {
            exit('编译文件目录templates_c不存在!请手工创建!');
        }
        if (!is_dir($this->cache_dir)) {
            exit('缓存文件目录'.$this->cache_dir.'不存在!请手工创建!');
        }
    }
    
    //模板变量注入方法
    public function assign($tpl_var, $var = null) {
        if (isset($tpl_var) && !empty($tpl_var)) {
            $this->_tpl_var[$tpl_var] = $var;
        } else {
            exit('模板变量名没有设置好');
        }
    }
    
    //文件编译
    public function display($file) {
        //模板文件
        $tpl_file  = $this->template_dir.'/'.$file;
        if (!file_exists($tpl_file)) {
            exit('ERROR:模板文件不存在!');
        }
        //编译文件
        $parse_file = $this->compile_dir.'/'.md5($file).$file.'.php';
        
        //只有当编译文件不存在或者是模板文件被修改过了
        //才重新编译文件
        if (!file_exists($parse_file) || filemtime($parse_file) < filemtime($tpl_file)) {
            include 'smarty_compile.class.php';
            $compile = new Smarty_Compile($tpl_file);
            $compile->parse($parse_file);
        }
        
        //开启了缓存才加载缓存文件,否则直接加载编译文件
        if ($this->caching) {
            //缓存文件
            $cache_file = $this->cache_dir.'/'.md5($file).$file.'.html';
            //只有当缓存文件不存在,或者编译文件已被修改过
            //重新生成缓存文件
            if (!file_exists($cache_file) || filemtime($cache_file) < filemtime($parse_file)) {
                //引入缓存文件
                include $parse_file;
                //缓存内容
                $content = ob_get_clean();
                //生成缓存文件
                if (!file_put_contents($cache_file, $content)) {
                    exit('缓存文件生成出错!');
                }
            }
            //载入缓存文件
            include $cache_file;
        } else {
            //载入编译文件
            include $parse_file;
        }
    }
}

  B.然后再新建一个MiniSmarty模板引擎解析器类文件:MiniSmarty_Compile.class.php

  其代码如下:

<?php
/**
 * MiniSmarty模板引擎
 * @link http://www.cnblogs.com/isuhua/
 * @author 华仔_suhua <weibo.com/suhua123>
 * @package MiniSmarty
 * @version 0.0.0.1
 */
class MiniSmarty_Compile {
    //模板内容
    private $content = '';
    
    //构造函数
    public function __construct($tpl_file) {
        $this->content = file_get_contents($tpl_file);
    }
    
    //解析普通变量,如把{$name}解析成$this->_tpl_var['name']
    public function parseVar() {
        $pattern = '/\{\$([\w\d]+)\}/';
        if (preg_match($pattern, $this->content)) {
            $this->content = preg_replace($pattern, '<?php echo \$this->_tpl_var["$1"]?>', $this->content);
        }
    }
    
    //这里可以自定义其他解析器...
    
    //模板编译
    public function parse($parse_file) {
        //调用普通变量解析器
        $this->parseVar();
        //这里可以调用其他解析器...
        
        //编译完成后,生成编译文件
        if (!file_put_contents($parse_file, $this->content)) {
            exit('编译文件生成出错!');
        }
    }
}
?>

  C.最后,还必须新建几个目录,分别是模板文件目录templates、编译文件目录template_c、缓存文件目录cache。

  如果你(ˇˍˇ)想~一次性成功,就必须创建这几个目录,缺一不可。否则就会报错,然后要求你手动创建。

  D.来试试看吧,编写demo.php,测试一下自定义的迷你版MiniSmarty模板引擎吧!

  demo.php代码如下:

//引入模板引擎
    require 'MiniSmarty.class.php';
    //实例化模板类
    $minismarty = new MiniSmarty();
    //缓存开关
    $minismarty->caching = true;
    
    //定义变量
    $webname = '迷你版Smarty测试';
    $author = 'suhua';
    $title = '这是一个测试标题';
    $content = '这是一段测试内容';
    
    //注入变量
    $minismarty->assign('webname', $webname);
    $minismarty->assign('author', $author);
    $minismarty->assign('title', $title);
    $minismarty->assign('content', $content);
    
    //启动编译模板文件
    $minismarty->display('demo.tpl');

  测试前,请先看一下template、template_c以及cache目录各自的状态,请看下图:

  E:打开浏览器,输入http://localhost/MiniSmarty/demo.php,即可看到一下效果:

  测试后,请再次看一下各目录的状态:

  在template_c目录和cache目录下都分别多了一个xxxx.tpl.php和xxx.tpl.html文件,为什么呢?

  答:这就是模板引擎非常重要的一个作用,编译文件并生成静态文件。对于如何实现的,这里不做解析,源码已经给出,看看就懂。

  ---->至此表示自己开发的一个迷你版Smarty模板引擎成功!*\(^v^)/*

  再次测试一下缓存功能是否生效了,首先修改demo.php中的代码,改动如下:

把 $author = 'suhua'; 修改为 $author = 'xiwang';

  改动过后,记得保存,然后再次刷新页面,看出现什么状况了?

  结果是:没有任何变化!这就正常了否则缓存功能没有实现。

  ???为什么没有任何变化呢

  答:原因是我们在demo.php中开启了缓存功能

//缓存开关
$minismarty->caching = true;

  请看代码。下面这段代码是MiniSmarty.class.php里面的,下面就是根据你是否开启缓存,决定是加载缓存文件还是编译文件。因为这里开启了,所以会直接加载缓存文件,所以就算你修改了原来的模板,依然没变化。

//开启了缓存才加载缓存文件,否则直接加载编译文件
        if ($this->caching) {
            //缓存文件
            $cache_file = $this->cache_dir.'/'.md5($file).$file.'.html';
            //只有当缓存文件不存在,或者编译文件已被修改过
            //重新生成缓存文件
            if (!file_exists($cache_file) || filemtime($cache_file) < filemtime($parse_file)) {
                //引入缓存文件
                include $parse_file;
                //缓存内容
                $content = ob_get_clean();
                //生成缓存文件
                if (!file_put_contents($cache_file, $content)) {
                    exit('缓存文件生成出错!');
                }
            }
            //载入缓存文件
            include $cache_file;
        } else {
            //载入编译文件
            include $parse_file;
        }

  如果我在demo.php中把缓存功能关了呢,结果会如何?

  即改动如下:

//缓存开关
 $minismarty->caching = false; //关闭缓存功能

  此时,当你再次刷新页面的时候,你会看到如下效果:

  此时,作者一栏改变了,这说明了模板引擎此时并没有去加载缓存文件,而是直接加载了编译文件。所以会出现该效果。上面的代码也说明了这一点。

  其他细节在源码中都有较详细的注释,在这里就不多说了,说一下其原理。

  ★MiniSmarty模板引擎原理:(非常重要)

  其原理也比较简单

  ①首先模板引擎会加载模板文件templates/demo.tpl,然后调用模板编译类对其进行编译解析(说白了就是变量替换或者标签替换),编译后就会生成编译文件xxxx.tpl.php;

  ②然后判断缓存是否开启,来决定是否生成缓存文件。其生成过程是:直接把xxx.tpl.php编译文件加载进来,然后再从缓冲区取出所有内容,清空缓冲区,把内容写入到缓存文件中xxx.tpl.html文件。

  ③模板文件demo.tpl是一个同时具有html和引擎标签的复合文件,编译文件xxx.tpl.php是把引擎标签替换成php代码,是具有php和html标签的复合文件,缓存文件xxx.tpl.html文件就是一个纯html的静态文件;

  至此,迷你版MiniSmarty模板引擎开发完成!

  其中,如果还有其他不好的地方,希望各位指出!谢谢。

  最后附上:MiniSmarty源码.rar(点击即可下载)

  学而时习之,不亦说乎?有朋自远方来,不亦乐乎?*(^v^)/*

  原文地址:https://www.cnblogs.com/isuhua/archive/2013/04/13/3019377.html

本站原创内容,转载请注明来源:https://www.liutonghui.com/33

PHP动态滚屏无刷新加载数据
上一篇 2013-10-24
PHP隐藏文件真实下载地址防盗链功能
下一篇 2013-12-06

评论列表(0条)

  • 暂无评论

发表评论

captcha

相关推荐

  • 深入浅出之Smarty模板引擎工作机制(一)

      深入浅出Smarty模板引擎工作机制,我们将对比使用smarty模板引擎和没使用smarty模板引擎的两种开发方式的区别,并动手开发一个自己的模板引擎,以便加深对smarty模板引擎工作机制的理解。   在没有使用Smarty模板引擎的情况下,我们都是将PHP程序和网页模板合在一起编辑的,好比下面的源代码: &lt;?php $title="深处浅出之Smarty模板引擎工作机制"; $content="Smarty模板引擎原理流程......

    2014-08-18
    18170
  • 深入浅出之Smarty模板引擎工作机制(二)

      源代码下载地址:深入浅出之Smarty模板引擎工作机制   接下来根据以下的Smarty模板引擎原理流程图开发一个自己的模板引擎用于学习,以便加深理解。   Smarty模板引擎的原理,其实是这么一个过程:   把模板文件编译成php文件,然后每次都去读取下模板的修改时间,没有修改就不编译。然后include这个&ldquo;编译&rdquo;后的PHP文件。   所谓编译也就是模板用正则替换成含PHP代码的过程。   实际上并不......

    2014-08-18
    14370
  • PHP框架的实现原理

      PHP框架的实现原理是通过采用MVC模式、路由机制、依赖注入、模板引擎和数据库操作等技术,构建一个结构清晰、易于维护和扩展的应用程序框架。下面是一个简单的PHP框架示例,演示了基本的实现原理:   简单的PHP框架文件结构 /simple_framework |-- app | |-- controllers | | |-- HomeController.php | |-- models | | ......

    2017-10-04
    15482
  • Web页面切换深色模式的实现原理

      要实现页面切换深色模式并记住用户使用的模式,可以结合使用 JavaScript 和本地存储(LocalStorage 或 Cookies)。以下是一个简单的示例:   HTML 页面结构: &lt;!DOCTYPE html&gt; &lt;html lang="en"&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content......

    2019-06-26
    20742
  • 球迷都是不懂球的球盲,请最懂球的懂大砖家教教

      国足烂是烂到跟粑粑一样,但却总有些小丑唱反调,自称是全国最懂球的董路懂大砖家却说巩汉林和全国球迷不懂球,都是球盲。还把球员在场上的消极怠慢,敷衍比赛说成了什么&ldquo;保护性接应&rdquo;,真是无耻又无知。到底是球迷不懂球,还是你懂大砖家不懂球。   作为全国政协委员,巩汉林表示:&ldquo;我是不懂球,但我能看懂比分。我们的国足队员,年薪千万,却不进球&rdquo;,由此引发了很多球迷的心声,中国足球真是烂的跟粑粑一样......

    2022-04-18
    10220
  • 梅西圆梦世界杯冠军,职业生涯圆满无遗憾

      2022年卡塔尔世界杯落下了帷幕,阿根廷队以7:5艰难的战胜了法国队,获得了本届世界杯冠军。梅西还拿到了本届世界杯的最佳球员奖项。梅西在赛后激动的捧起并亲吻大力神杯,这一刻他终于圆了自己的世界杯冠军梦。   在赛前很多球迷预测法国队将会战胜阿根廷队卫冕本届冠军,因为从球员的阵容和状态来看,法国队的优势更明显一些。比赛的过程真的是一波三折,充满了跌宕起伏的戏剧性。阿根廷队一度场面占优,上半场梅西点球破门,随后迪马利亚进球,让阿根廷队......

    2022-12-19
    10040
  • 华为Mate60手机开售,麒麟5G芯片回归,遥遥领先

      没开发布会,没有预告就直接开卖备受关注的旗舰手机,华为Mate60系列算是开了个头。这几天华为登上了热搜,这次是因为华为Mate60手机携带&ldquo;麒麟芯片&rdquo;提前开售,瞬间售罄,同时也标志着麒麟5G芯片的正式回归。这一消息在各大主流媒体平台上迅速引发热议,网友们纷纷发表意见,自媒体人也争相蹭热度,提出各自观点。   如果你打开华为商城app,可以看到华为已经在自家商城上架了华为Mate60系列手机,而这些手机已经......

    2023-08-31
    11930
  • 老百姓不是不会花钱,而是没有钱花

      白岩松最近在节目中与专家侃侃而谈,两个有钱人一副假模假式的样子在研究怎么让没钱的老百姓花钱,可以说是把虚伪发挥的淋漓尽致。   老百姓是不会花钱吗?花钱还用你们教吗,有钱谁不会花?专家们高谈阔论如何刺激消费的时候,却忽视了一个基本事实:许多老百姓,特别是中低收入群体,并没有足够的可支配收入来满足他们的基本消费需求。   专家们常常引用数据来说明中国消费者的消费习惯和偏好,认为只要政策得当,就能够激发消费者更多的消费欲望。但是,他们......

    2024-01-09
    6720