PHP的模板引擎smarty原理是什么(整理)

一、总结

一句话总结:其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者混合为一个php的混编文件,然后执行这个混编文件。

1、smarty模板引擎的主要作用是什么?

smarty模板技术,可以让数据和视图进行分离,让视图中不能直接出现php代码。这样的话,让前段页面的开发和后台数据的开发,可以双管齐下,同时进行了。

2、smarty的两个函数的主要作用是什么?

smarty模板的使用比较简单,主要有两个非常核心的函数。一个是assign(),把模板中要使用的数据进行预赋值,一个是display(),用来解析和展示最后的视图模板。

  使用的简单代码如下:

  1. include_once "Smarty.class.php";//引入smarty类
  2.  
  3. $smarty = new Smarty;//创建smarty对象
  4.  
  5. $smarty->assign("name","zhangmiao");//赋值,以备模板中使用
  6. $smarty->assign("age","18");
  7.  
  8. $smarty->display('index.tpl');//引入模板,展示视图页面

3、我们模板中没有php代码,我们只用了{$name}和{$age}就能把对应的变量给展示了出来,是为什么呢?

然后,我们一看smarty编译后的文件是这样的:

  1. <h1>测试模板1</h1>
  2. 我的名字是:<?php echo $this->var["name"]; ?><br/>
  3. 我的年纪是:<?php echo $this->var["age"]; ?><br/>

原来如此,最终还是变成了含有php代码的模板,但是这个模板中把标签转成php代码的工作,我们交给了smarty模板引擎来完成的。

那到底smarty模板引擎是怎么把模板里面的非php代码的标签,转变成被最终可以解析执行的php代码的呢?

主要思路是:替换。

分成了两步:

  1、用过assign函数把要解析的标签变量赋值

  2、通过display函数把标签替换成对象的php变量

我们根据这个思路,自己也写了个简易版的smarty模板引擎,算是多smarty模板引擎设计原理的一种理解。但是只能解析单个变量的标签,其他标签均没有处理。核心代码如下:

  1. //获取模板源文件,用来替换
  2. $template_content = file_get_contents($template_path);
  3.  
  4. $pattern = array(
  5. '/\{\s*\$([a-zA-Z][a-zA-Z0-9_]*)\s*\}/i'
  6. );
  7. $replace = array(
  8. '<?php echo $this->var["${1}"]; ?>'
  9. );
  10. //用正则去替换模板源文件中的变量符号{$varname}
  11. $res = preg_replace($pattern,$replace,$template_content);
  12. //编译后文件写入某个目录
  13. file_put_contents($template_c_path,$res);

4、smarty模板引擎里面的display函数的最核心的操作是什么?

替换

把标签的内容替换成php的内容

例如把

  1. <h1>测试模板1</h1>
  2. 我的名字是:{$name}<br/>
  3. 我的年纪是:{$age}<br/>

替换为:

  1. <h1>测试模板1</h1>
  2. 我的名字是:<?php echo $this->var["name"]; ?><br/>
  3. 我的年纪是:<?php echo $this->var["age"]; ?><br/>

二、PHP的模板引擎smarty原理浅谈

  mvc是开发中的一个伟大的思想,使得开发代码有了更加清晰的层次,让代码分为了三层各施其职、无论是对代码的编写以及后期的阅读和维护,都提供了很大的便利。

  我们在php开发中,视图层view是不允许有php代码来操作数据库之类的来获取数据的,我们一般都会在控制器层controller,就已经把视图层要展示的数据准备好,方便视图层直接用来展示。

  smarty模板技术,可以让数据和视图进行分离,让视图中不能直接出现php代码。这样的话,让前段页面的开发和后台数据的开发,可以双管齐下,同时进行了。

  

  smarty模板的使用比较简单,主要有两个非常核心的函数。一个是assign(),把模板中要使用的数据进行预赋值,一个是display(),用来解析和展示最后的视图模板。

  使用的简单代码如下:

  1. include_once "Smarty.class.php";//引入smarty类
  2.  
  3. $smarty = new Smarty;//创建smarty对象
  4.  
  5. $smarty->assign("name","zhangmiao");//赋值,以备模板中使用
  6. $smarty->assign("age","18");
  7.  
  8. $smarty->display('index.tpl');//引入模板,展示视图页面

我们看下模板源代码是这样的:

  1. <h1>测试模板1</h1>
  2. 我的名字是:{$name}<br/>
  3. 我的年纪是:{$age}<br/>

浏览器页面是这样的:

疑问:我们模板中没有php代码,我们只用了{$name}和{$age}就能把对应的变量给展示了出来,是什么鬼呢?

然后,我们一看smarty编译后的文件是这样的:

  1. <h1>测试模板1</h1>
  2. 我的名字是:<?php echo $this->var["name"]; ?><br/>
  3. 我的年纪是:<?php echo $this->var["age"]; ?><br/>

原来如此,最终还是变成了含有php代码的模板,但是这个模板中把标签转成php代码的工作,我们交给了smarty模板引擎来完成的。

那到底smarty模板引擎是怎么把模板里面的非php代码的标签,转变成被最终可以解析执行的php代码的呢?

主要思路是:替换。

分成了两步:

  1、用过assign函数把要解析的标签变量赋值

  2、通过display函数把标签替换成对象的php变量

我们根据这个思路,自己也写了个简易版的smarty模板引擎,算是多smarty模板引擎设计原理的一种理解。但是只能解析单个变量的标签,其他标签均没有处理。代码如下:

  1.  
  1. class MySmarty{
  2.  
  3. //模板存放路径
    public $template = './template/';
    //编译后模板路径
    public $template_c = './template_c/';
  4.  
  5. //存放变量的数组,通过assign函数赋值
    public $var = array();
  6.  
  7. //变量赋值
    public function assign($vkey,$value){
    if($vkey != ""){
    $this->var[$vkey] = $value;//把要模板中解析的数据压入数组
    }
    }
  8.  
  9. //模板中变量替换
    public function display($path){
    $template_path = $this->template.$path;
    $template_c_path = $this->template_c.$path.".php";
    if(!file_exists($template_path)){
    return false;
    }
  10.  
  11. //只有解析后的模板文件不存在或者模板源文件有新的改动的情况下 重新解析模板
    if(!file_exists($template_c_path) || filemtime($template_path)>filemtime($template_c_path)){
    //获取模板源文件,用来替换
    $template_content = file_get_contents($template_path);
  12.  
  13. $pattern = array(
    '/\{\s*\$([a-zA-Z][a-zA-Z0-9_]*)\s*\}/i'
    );
    $replace = array(
    '<?php echo $this->var["${1}"]; ?>'
    );
    //用正则去替换模板源文件中的变量符号{$varname}
    $res = preg_replace($pattern,$replace,$template_content);
    //编译后文件写入某个目录
    file_put_contents($template_c_path,$res);
    }
    //引入编译后文件,其实就是执行了那个php文件的代码
    include_once $template_c_path;
  14.  
  15. }
    }
  1.  

我们调用自己的assign和display放入引入,也能正常解析使用啦

参考:PHP的模板引擎smarty原理浅谈 - 水聊鱼默默 - 博客园
https://www.cnblogs.com/zmfly/p/6548761.html

三、Smarty模板执行原理

为了实现程序的业务逻辑和内容表现页面的分离从而提高开发速度,php 引入了模板引擎的概念,php 模板引擎里面最流行的可以说是smarty了,smarty因其功能强大而且速度快而被广大php web开发者所认可。本文将记录一下smarty模板引擎的工作执行原理,算是加深一下理解。

其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者混合为一个php的混编文件,然后执行这个混编文件。基本上就是这么回事儿了。下面以smarty为例说下这个过程。

例如文章页面:http://www.phpernote.com/article.php?id=795

一般处理过程是这样的:

html模板页面部分代码(article.html):

  1. <body>
  2. <div>{subject}</div>
  3. <div>{content}</div>
  4. </body>

php页面逻辑部分代码:

  1. $subject='smarty视频教程分享';
  2. $content='smarty视频教程分享,下面是具体的下载地址,有需要的朋友可以看看,对smarty模板讲解的非常详细,作者粗略看了一下目录,真是详细到细枝末节该......';
  3. $str=file_get_contents('article.html');
  4. $str=str_replace('{subject}',$subject,$str);
  5. $str=str_replace('{content}',$content,$str);
  6. echo $str;

使用面向对象技术实现模板功能的封装代码如下:

  1. <?php
  2. class Template{
  3. //属性
  4. public $vars; //保存要替换的标记和数据的内容
  5. public $left_delimiter='{*'; //左分隔符
  6. public $right_delimiter='*}'; //右分隔符
  7. //方法
  8. public function assign($key,$value){
  9. $this->vars[$key]=$value;
  10. }
  11. public function display($file){//file表示模板名
  12. $str=file_get_contents($file);//从模板中读取多有内容,并将内容放入$str中
  13. foreach ($this->vars as $key => $value){ //$key 键名(模板标记) $value 值
  14. $str=str_replace($this->left_delimiter.$key.$this->right_delimiter, $value, $str);
  15. }
  16. echo $str;
  17. //file_put_contents('bak.html', $str);
  18. }
  19. }

注意:assign(‘name’,’zhangsan’);这句的时候其实还没有进行数据替换,而是把传入的数据保存在vars[]中,当display的时候才进行数据替换。

smarty的处理过程:

1、 smarty将php源文件,首先编译成中间文件

2、 如果启用缓存,再根据编译文件生成缓存文件

3、 之后每次访问都会访问编译文件

如果启用缓存文件而且有缓存文件并且缓存文件没有过期,则直接访问缓存文件(先不考虑缓存的时候的流程)编译文件里时间戳记录模板文件修改时间,如果模板被修改过就可以检测到,然后重新编译。

(编译是把静态内容保存起来,动态内容根据传入的参数不同而不同)

读取编译文件省去了读取模板文件,和字符串替换的时间,所以可以更快。

第一次请求article.php时候编译,产生编译文件,在编译文件里。

第二次请求article.php的时候,判断模板文件是否改变,如果模板文件已改变,那么去读取模板文件,然后再编译,如果没有改变,则去读取编译文件,编译文件最终输出;

缓存默认是关闭的;缓存是把数据彻底的存在缓存文件里,直到缓存文件过期才会重新来缓存;所以说smarty在一些实时性特别强的网站里不是特别合适;

对于以上文字可以抽象的理解为下面的一幅图,读者自己去体会吧!

考虑缓存:

在smarty程序里,判断是否开启了缓存文件,并且缓存文件没有过期,,就去找缓存文件,如果没有开启缓存文件,就去判断模板文件,如果缓存文件已过期,也是去判断模板文件。

参考:Smarty模板执行原理 - CSDN博客
https://blog.csdn.net/u013474436/article/details/50010955

 
 

PHP的模板引擎smarty原理是什么(整理)的更多相关文章

  1. PHP的模板引擎smarty原理浅谈

    mvc是开发中的一个伟大的思想,使得开发代码有了更加清晰的层次,让代码分为了三层各施其职.无论是对代码的编写以及后期的阅读和维护,都提供了很大的便利. 我们在php开发中,视图层view是不允许有ph ...

  2. php模板原理PHP模板引擎smarty模板原理浅谈

    mvc是开发中的一个伟大的思想,使得开发代码有了更加清晰的层次,让代码分为了三层各施其职.无论是对代码的编写以及后期的阅读和维护,都提供了很大的便利. 我们在php开发中,视图层view是不允许有ph ...

  3. Vue.js双向绑定的实现原理和模板引擎实现原理(##########################################)

    Vue.js双向绑定的实现原理 解析 神奇的 Object.defineProperty 这个方法了不起啊..vue.js和avalon.js 都是通过它实现双向绑定的..而且Object.obser ...

  4. 浅谈dedecms模板引擎工作原理及其自定义标签

    浅谈dedecms模板引擎工作原理: 理解织梦模板引擎有什么意思? 可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步. 理解织梦会使我们写PHP代码是更顺手,同时能学 ...

  5. PHP模板引擎Smarty内建函数section,sectionelse用法详解

    本文实例讲述了PHP模板引擎Smarty内建函数section,sectionelse用法.分享给大家供大家参考,具体如下: section 是 Smarty 模板中除了 foreach 以外的另一种 ...

  6. 高性能JavaScript模板引擎实现原理详解

    这篇文章主要介绍了JavaScript模板引擎实现原理详解,本文着重讲解artTemplate模板的实现原理,它采用预编译方式让性能有了质的飞跃,是其它知名模板引擎的25.32 倍,需要的朋友可以参考 ...

  7. JavaScript 模板引擎实现原理解析

    1.入门实例 首先我们来看一个简单模板: <script type="template" id="template"> <h2> < ...

  8. (转)浅谈dedecms模板引擎工作原理及自定义标签

    理解织梦模板引擎有什么意义?一方面可以更好地自定义标签.更多在于了解织梦系统,理解模板引擎是理解织梦工作原理的第一步.理解织梦会使我们写php代码时更顺手,同时能学习一些php代码的组织方式. 这似乎 ...

  9. Php模板引擎Smarty安装和配置

    Smarty 是PHP的一个模板引擎,是由Monte Ohrt 和 Andrei Zmievski 使用PHP语言开发的,发展至今已成为一个非常流行的模板引擎,Smarty 提供了一种易于管理和使用的 ...

随机推荐

  1. tomcat:Could not publish to the server. java.lang.IndexOutOfBoundsException

    1.将工程加入到tomcat,报上述错误 2. run--maven build 报jar包错误: invalid LOC header (bad signature) 3.根据提示找到上述jar包, ...

  2. IE(8~11+) 可用右键加速器

    必应词典工具 立即安装: 网络安装:http://dict.bing.com.cn/tools_dl.aspx?dl=ie8acc&mkt=ZH-CN 开发示例: <?xml versi ...

  3. 提高realm存储速率

    我的数据量大约有2.5M,但是完全存储到数据库差不多用了11秒,有没有比较好的方法提高存储效率 提高realm存储速率 >> android这个答案描述的挺清楚的:http://www.g ...

  4. form表单提交的时候,传过去的值是键值对的形式

    效果展示 第一种需求,点击input的时候,input的value发生改变 $('.group-wrapper input').click(function(){ $(this).val(0); // ...

  5. linux傻瓜式安装lnmp

    一.百度 https://lnmp.org/install.html 二.点击 <安装> 三.登录 linux cd /usr/local/ wget -c http://soft.vps ...

  6. [HAOI2006]旅行(并查集)

    寒假填坑五十道省选题——第五道 [HAOI2006]旅行 题目描述 Z小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光.Z小镇附近共有N个景点(编号为1,2,3,…,N),这些景点被M条道路 ...

  7. CMSIS-RTOS 时间管理之虚拟定时器Virtual Timers

    虚拟定时器Virtual Timers CMSIS-RTOS API里有几个向下计数的虚拟定时器,它们实现计数完成时用户的回调功能.每个定时器都可以配置成单次计数或重复计数模式,它们可以在定义定时器结 ...

  8. 【Codeforces Round #239 (Div. 1) B】 Long Path

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] DP,设f[i]表示第一次到i这个房间的时候传送的次数. f[1] = 0,f[2] = 2 考虑第i个位置的情况. 它肯定是从i- ...

  9. 使用安卓手机连接win7的热点

    转载自:http://bbs.tgbus.com/thread-2354596-1-1.html 附件下载 亲测可用: wifi信号是满格的

  10. CO-PRIME(初探 莫比乌斯)NYOJ1066(经典)gcd(a,b)=1

    CO-PRIME 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 This problem is so easy! Can you solve it? You are ...