最近在开发的时候,遇到了在有html模板的情况下,每天生成数据报表的需求,如果用框架太重了,就想自己简单的模板来实现,这样简单实用,顺便记录下原理。
一. 模板引擎原理
php是网页内嵌型的语言,利用〈?php ?〉标签嵌入到html文本中,然后由php的解释器去执行,动态生成页面。 但是对于大型的web应用,一般分为前端, 后台业务逻辑,及数据层。为了项目协作和分工,当然需要将前端和业务逻辑分离,前端专注于界面展示,后端程序负责逻辑处理。 这样使得改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻辑,这在多人合作的项目中显的尤为重要。
分离之后的两部分怎么实现连接呢? 逻辑层的数据如何传递给模板页面呢? 模板页面的动态数据项采用什么规则预先展示呢?
这是就需要这样一个“桥梁”来解决这个问题,即 模板引擎。
一般来说需要两个类来实现,分别是模板引擎入口类和模板解析类。 mytpl.class.php文件通常定义一个类MyTpl,类中需定义一个数组tpl_var[]用于存放tpl.html中自定义内容标签的参数。MyTpl.Compile.class.php,解析模板文件,的是将tpl.hml中无法识别的的内容标签转换成PHP语句,编译成“templates_c”文件夹下的tpl_c.html中。
所以一般的模板引用步骤为:
include “mytpl.class.php文件”;//加载模板引擎 $tpl = new MyTpl();//实例化一个模板类 $title = “标题”; $content = “内容”; $tpl->assign(“title”,$title);//调用模板类中的方法,分配变量 $tpl->assign(“content”,$content); $tpl->display(“tpl.html”);//调用模板类中的方法,用于显示编译后的内容
整个流程如图所示:
二. 模板引擎简单实现
以下实现了一个最简单的模板引擎,不含模板解析类:
tpl.html: <html> <body> <?php echo $str ?> <br /> <?php print_r($arr) ?> </body> </html>
Mytpl.php: <?php //include 包含其他文件 //extract 的作用:从数组中将变量导入到当前的符号表,键做变量,值做值! class Mytpl { public $tpl_vars; public $key; public $val; public function assign($tpl_var,$value){ if (is_array($tpl_var)) { foreach ($tpl_var as $_key => $_val) { if ($_key != '') { $this->tpl_vars[$_key] = $_val; } } } else { if ($tpl_var != '') { $this->tpl_vars[$tpl_var] = $value; } } } public function display($tpl){ $this->assign($this->key,$this->val); extract($this->tpl_vars); if(file_exists($tpl)){ //模板存在就加载文件。 //include $tpl; ob_start(); include $tpl; $contents = ob_get_contents(); ob_end_clean(); return $contents; }else{ return false; } } } $tpl = new Mytpl; $arr = array('a'=>'aaaaaaa','b'=>array('a'=>'111111','b'=>'22222','c'=>'3333'),'c'=>'ccccccc','d'=>'dddddd','e'=>'eeeee'); $str = '我是字符串'; $tpl->assign('arr',$arr); $tpl->assign('str',$str); $message = $tpl->display('tpl.html'); echo $message; ?>
其中使用到了extract函数,从数组中将变量导入到当前的符号表,键做变量,值做值!
同时导入模板使用了include 函数,从include该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。当一个文件被包含时,语法解析器在目标文件的开头脱离 PHP 模式并进入 HTML 模式,到文件结尾处恢复。由于此原因,目标文件中需要作为 PHP 代码执行的任何代码都必须被包括在有效的 PHP 起始和结束标记之中。(所以需要模板解析类编译模板)。同时将inlcude的文件“包含”到一个变量中的方法是用输出控制函数结合 include 来捕获其输出。
如果template文件没有改动,那麽该模板文件就不需要被重新编译,所以可以在模板引擎中添加缓存机制,提升访问速度。
Smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一,定义了smarty的语法规则和缓存等特性,性能和使用性都非常好。