简单的自定义php模板引擎

模板引擎的思想是来源于MVC(Model View Controller)模型,即模型层、视图层、控制器层。

在Web端,模型层为数据库的操作;视图层就是模板,也就是Web前端;Controller就是PHP对数据和请求的各种操作。模板引擎就是为了将视图层和其他层分离开来,使php代码和html代码不会混杂在一起。因为当php代码和html代码混杂在一起时,将使代码的可读性变差,并且代码后期的维护会变得很困难。

大部分的模板引擎原理都差不多,核心就是利用正则表达式解析模板,将约定好的特定的标识语句编译成php语句,然后调用时只需要include编译后的文件,这样就讲php语句和html语句分离开来了。甚至可以更进一步将php的输出输出到缓冲区,然后将模板编译成静态的html文件,这样请求时,就是直接打开静态的html文件,请求速度大大加快。

简单的自定义模板引擎就是两个类,第一个是模板类、第二个是编译类。

首先是编译类:

class CompileClass { private $template; // 待编译文件 private $content; // 需要替换的文本 private $compile_file; // 编译后的文件 private $left = '{'; // 左定界符 private $right = '}'; // 右定界符 private $include_file = array(); // 引入的文件 private $config; // 模板的配置文件 private $T_P = array(); // 需要替换的表达式 private $T_R = array(); // 替换后的字符串 public function __construct($template, $compile_file, $config) {} public function compile() { $this->c_include(); $this->c_var(); $this->c_staticFile(); file_put_contents($this->compile_file, $this->content); } // 处理include public function c_include() {} // 处理各种赋值和基本语句 public function c_var() {} // 对静态的JavaScript进行解析 public function c_staticFile() {} }

编译类的大致结构就是上面那样,编译类的工作就是根据配置的文件,将写好的模板文件按照规则解析,替换然后输出到文件中。这个文件的内容是php和html混杂的,但在使用模板引擎进行开发时并不需要在意这个文件,因为我们要编写的是模板文件,也就是html和我们自己定义的标签混合的一个文件。这样View和其他两层就分离开来了。

在这个自定义模板引擎中,我的左右定界符就是大括号,具体的解析规则就是放在__construct()中

// 需要替换的正则表达式 $this->T_P[] = "/$this->left\s*\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\xf7-\xff]*)\s*$this->right/"; $this->T_P[] = "/$this->left\s*(loop|foreach)\s*\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\xf7-\xff]*)\s*$this->right/"; $this->T_P[] = "/$this->left\s*(loop|foreach)\s*\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\xf7-\xff]*)\s+" . "as\s+\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\xf7-\xff]*)$this->right/"; $this->T_P[] = "/$this->left\s*\/(loop|foreach|if)\s*$this->right/"; $this->T_P[] = "/$this->left\s*if(.*?)\s*$this->right/"; $this->T_P[] = "/$this->left\s*(else if|elseif)(.*?)\s*$this->right/"; $this->T_P[] = "/$this->left\s*else\s*$this->right/"; $this->T_P[] = "/$this->left\s*([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\xf7-\xff]*)\s*$this->right/"; // 替换后的字符串 $this->T_R[] = "<?php echo \$\\1; ?>"; $this->T_R[] = "<?php foreach((array)\$\\2 as \$K=>\$V) { ?>"; $this->T_R[] = "<?php foreach((array)\$\\2 as &\$\\3) { ?>"; $this->T_R[] = "<?php } ?>"; $this->T_R[] = "<?php if(\\1) { ?>"; $this->T_R[] = "<?php } elseif(\\2) { ?>"; $this->T_R[] = "<?php } else { ?>"; $this->T_R[] = "<?php echo \$\\1; ?>";

上面的解析规则包含了基本的输出和一些常用的语法,if、foreach等。利用preg_replace函数就能对模板文件进行替换。具体情况如下

<!--模板文件--> {$data} {foreach $vars} {if $V == 1 } <input value="{V}"> {elseif $V == 2} <input value="123123"> {else } <input value="sdfsas是aa"> {/if} {/foreach} { loop $vars as $var} <input value="{var}"> { /loop } // 解析后 <?php echo $data; ?> <?php foreach((array)$vars as $K=>$V) { ?> <?php if( $V == 1) { ?> <input value="<?php echo $V; ?>"> <?php } elseif( $V == 2) { ?> <input value="123123"> <?php } else { ?> <input value="sdfsas是aa"> <?php } ?> <?php } ?> <?php foreach((array)$vars as &$var) { ?> <input value="<?php echo $var; ?>"> <?php } ?>

编译类的工作大致就是这样,剩下的include和对JavaScript的解析都和这个大同小异。

然后就是模板类

class Template { // 配置数组 private $_arrayConfig = array( 'root' => '', // 文件根目录 'suffix' => '.html', // 模板文件后缀 'template_dir' => 'templates', // 模板所在文件夹 'compile_dir' => 'templates_c', // 编译后存放的文件夹 'cache_dir' => 'cache', // 静态html存放地址 'cache_htm' => false, // 是否编译为静态html文件 'suffix_cache' => '.htm', // 设置编译文件的后缀 'cache_time' => 7200, // 自动更新间隔 'php_turn' => true, // 是否支持原生php代码 'debug' => 'false', ); private $_value = array(); private $_compileTool; // 编译器 static private $_instance = null; public $file; // 模板文件名 public $debug = array(); // 调试信息 public function __construct($array_config=array()) {} // 单步设置配置文件 public function setConfig($key, $value=null) {} // 注入单个变量 public function assign($key, $value) {} // 注入数组变量 public function assignArray($array) {} // 是否开启缓存 public function needCache() {} // 如果需要重新编译文件 public function reCache() {} // 显示模板 public function show($file) {} }

整个模板类的工作流程就是先实例化模板类对象,然后利用assign和assignArray方法给模板中的变量赋值,然后调用show方法,将模板和配置文件传入编译类的实例化对象中然后直接include编译后的php、html混编文件,显示输出。简单的流程就是这样,详细的代码如下

public function show($file) { $this->file = $file; if(!is_file($this->path())) { exit("找不到对应的模板文件"); } $compile_file = $this->_arrayConfig['compile_dir']. md5($file). '.php'; $cache_file = $this->_arrayConfig['cache_dir']. md5($file). $this->_arrayConfig['suffix_cache']; // 如果需要重新编译文件 if($this->reCache($file) === false) { $this->_compileTool = new CompileClass($this->path(), $compile_file, $this->_arrayConfig); if($this->needCache()) { // 输出到缓冲区 ob_start(); } // 将赋值的变量导入当前符号表 extract($this->_value, EXTR_OVERWRITE); if(!is_file($compile_file) or filemtime($compile_file) < filemtime($this->path())) { $this->_compileTool->vars = $this->_value; $this->_compileTool->compile(); include($compile_file); } else { include($compile_file); } // 如果需要编译成静态文件 if($this->needCache() === true) { $message = ob_get_contents(); file_put_contents($cache_file, $message); } } else { readfile($cache_file); } }

在show方法中,我首先判断模板文件存在,然后利用MD5编码生成编译文件和缓存文件的文件名。然后就是判断是否需要进行编译,判断的依据是看编译文件是否存在和编译文件的写入时间是否小于模板文件。如果需要编译,就利用编译类进行编译,生成一个php文件。然后只需要include这个编译文件就好了。

为了加快模板的载入,可以将编译后的文件输出到缓冲区中,也就是ob_start()这个函数,所有的输出将不会输出到浏览器,而是输出到默认的缓冲区,在利用ob_get_contents()将输出读取出来,保存成静态的html文件。

具体的使用如下

require('Template.php'); $config = array( 'debug' => true, 'cache_htm' => false, 'debug' => true ); $tpl = new Template($config); $tpl->assign('data', microtime(true)); $tpl->assign('vars', array(1,2,3)); $tpl->assign('title', "hhhh"); $tpl->show('test');  

缓存后的文件如下

<!DOCTYPE html> <html> <head> <title>hhhh</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> 1466525760.32 <input value="1"> <input value="123123"> <input value="sdfsas是aa"> <input value="1"> <input value="2"> <input value="3"> <script src="123?t=1465898652"></script> </body> </html>

一个简单的自定义模板引擎就完成了,虽然简陋但是能用,而且重点在于造轮子的乐趣和收获。 
完整代码可见我的 github

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-09-07 00:09:28

简单的自定义php模板引擎的相关文章

简单的自定义php模板引擎_php实例

模板引擎的思想是来源于MVC(Model View Controller)模型,即模型层.视图层.控制器层. 在Web端,模型层为数据库的操作:视图层就是模板,也就是Web前端:Controller就是PHP对数据和请求的各种操作.模板引擎就是为了将视图层和其他层分离开来,使php代码和html代码不会混杂在一起.因为当php代码和html代码混杂在一起时,将使代码的可读性变差,并且代码后期的维护会变得很困难.  大部分的模板引擎原理都差不多,核心就是利用正则表达式解析模板,将约定好的特定的标识

Node.js的Web模板引擎ejs的入门使用教程_node.js

Node 开源模板的选择很多,但推荐像我这样的老人去用 EJS,有 Classic ASP/PHP/JSP 的经验用起 EJS 来的确可以很自然,也就是说,你能够在 <%...%> 块中安排 JavaScript 代码,利用最传统的方式 <%=输出变量%>(另外 <%-输出变量是不会对 & 等符号进行转义的).安装 EJS 命令如下: npm install ejs JS 调用JS 调用的方法主要有两个: ejs.compile(str, options); // =

超越模板引擎

模板 总体来说,模板引擎是一个"好东西" 作为一个PHP/Perl的程序员,许多模板引擎(fastTemplate, Smarty, Perl的 HTML::Template)的用户,以及我自己的(bTemplate [1] 的作者),我讲这句话很多次了. 然而,在同事进行了长时间的讨论之后,我确信了大量的模板引擎(包括我自己写的)根本是错误的. 我想唯一的例外是Smarty [2],虽然我认为它太庞大了,并且考虑到这篇文章的其余部分相当的没有观点.然而,就你为什么选择Smarty(或

自定义min版smarty模板引擎MinSmarty.class.php文件及用法_php实例

本文实例讲述了自定义的min版smarty模板引擎MinSmarty.class.php文件.分享给大家供大家参考,具体如下: 一.smarty的优点 smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一.它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离.简单的讲,目的就是要使PHP程序员同前端人员分离,使程序员改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻

自定义min版smarty模板引擎MinSmarty.class.php文件及用法

本文实例讲述了自定义的min版smarty模板引擎MinSmarty.class.php文件.分享给大家供大家参考,具体如下: 一.smarty的优点 smarty是一个使用PHP写出来的模板引擎,是目前业界最著名的PHP模板引擎之一.它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离.简单的讲,目的就是要使PHP程序员同前端人员分离,使程序员改变程序的逻辑内容不会影响到前端人员的页面设计,前端人员重新修改页面不会影响到程序的程序逻

PHP模板引擎Smarty自定义变量调解器用法_php实例

本文实例讲述了PHP模板引擎Smarty自定义变量调解器用法.分享给大家供大家参考,具体如下: 在 PHP 中,有很多处理文本的函数,您可以把要处理的文本通过函数处理之后,再调用 Smarty 模板引擎中的 assign() 赋值给变量,分配到模板中进行显示. Smarty 中的变量调解器和 PHP 中处理文本的函数相似,不过语法不相同,在 Smarty 中,是通过 "|" 后面直接跟调解器函数名,如果有参数,得加在 ":" 后面,多个参数的话,累加即可. 格式:{

简单PHP模板引擎的实现例子

简单php教程模板引擎的实现例子 <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equ

php模板引擎技术简单实现_php实例

用了smarty,tp过后,也想了解了解其模板技术是怎么实现,于是写一个简单的模板类,大致就是读取模板文件->替换模板文件的内容->保存或者静态化  tpl.class.php主要解析 assign 方法实现      /** * 模板赋值操作 * @param mixed $tpl_var 如果是字符串,就作为数组索引,如果是数组,就循环赋值 * @param mixed $tpl_value 当$tpl_var为string时的值,默认为 null */ public function a

Javascript简单实现模板引擎例子

一.背景 有两个大项目是从RD那边迁移过来,因为项目初期FE无人力跟进,所以都是后端同学直接用Smarty完成的前端部分:所以考虑到迁移的成本和方案,索性升级一下当前的JS模板引擎. 二.大致方案 支持extends标签 支持block标签 1.标签语法 为了便于模板词法分析,在模板左定界符后加上@来标识,标签名替换为属性设置方式,如extends标签: <%@ extends="layout/layout.html" %> 2.extends实现方案 将整个extends