Home > Article > Backend Development > Sample code sharing for PHP's custom template engine
This article will introduce the template engine in PHP in detail. Has very good reference value. Let’s take a look at it with the editor
The previous words
In most project teams, developing a Web program will have such a process: Submission of plan documents After that, the front-end engineer made the appearancemodel of the website, and then handed it to the back-end engineer, who used the back-end code to implement the program logic, and used the appearance model to make the basicarchitecture, The project is then returned to the front-end engineers for further refinement. In this way, the project may go back and forth between back-end engineers and front-end engineers several times. Since the back-end engineer does not interfere with any related HTML tags, there is no need to mix front-end code and back-end code. Front-end engineers only need configuration files, dynamic blocks and other interface parts, and do not need to touch the intricate back-end code. Therefore, it is important to have a good template support at this time. This article will introduce the template engine in PHP in detail
Overview
What is a website template? To be precise, it refers to the website page template, that is, each page is just a template, including structure, style and page layout. It is a template for creating web page content, and can also be understood as an existing web pageframe. The original content in the template can be replaced with dynamic content from the server-side database, in order to keep the page style consistent
PHP is an HTML embedded scripting language executed on the server side, so most For web applications developed with PHP, the initial development template is mixed-layer data programming. Although the MVC design pattern can forcefully separate program application logic and web page rendering logic, it only separates the input, processing, and output of the application. The web page rendering logic (view) will also be strongly coupled with HTML code and PHP programs. . The writer of PHP scripts must be both a web designer and a PHP developer
There are many solutions that can almost completely separate the page design of the website from the PHP application. These solutions are called "template engines" and they are gradually eliminating the difficulties caused by the lack of hierarchical separation. The purpose of the template engine is to achieve the above-mentioned logical separation function. It allows program developers to focus on data control or function achievement. Therefore, the template engine is very suitable for use by the company's web development team, allowing everyone to exert their expertise. The core of the template engine technology is relatively simple. Just specify the front-end page as a template file, and define the dynamic content in this template file, such as database output, user interaction, etc., as "
variable" contained using special "delimiters", and then Place it in the corresponding location in the template file. When the user browses, the template file is opened by the PHP script program and the variables defined in the template file are replaced. In this way, when the special variables in the template are replaced with different dynamic content, the required page will be output Currently, there are many mature templates that can be applied in PHP, such as Smarty, PHPLIB, IPB Dozens more. Using these template engines written in PHP can make the code context clearer and the structure more rational. It can also make website maintenance and updates easier, create a better development environment, and make it easier to combine development and design work. However, no PHP template is the most suitable or perfect. Because PHP templates are popular things and are not developed for a certain person. If you can fully understand the advantages and disadvantages of templates based on a clear understanding of their characteristics and applications, you can know whether to choose to use a template engine or which template engine to use
Customize templates Engine classCustomize the template engine, which can better grasp the working mechanism of the template engine and prepare you for learning Smarty. More importantly, your own PHP template engine is never fixed and can be customized according to the needs of the project.
In the following example, your own PHP template engine is created through the template engine concept introduced earlier. A simple template engine that can be used to handle the basic functionality of templates. For example: variable substitution,
branch structure, arraylooptraversal, and nesting of templates, etc., as shown below: 在Mytpl类中声明的多个方法中,除被封装过的方法之外,只有两个公有方法assign()和display()在创建对象以后可以被凋用。其中assign()方法用来将PHP脚本中的数据分配给模板中对应的变量,display()方法则用来将特定的templates目录下的模板文件加载到PHP脚本中。同时将模板文件中使用“fa5e847075b157e00c9630361edd1a59>”标记声明的自定义模板语句,匹配出来并替换成相对应的PHP语法格式,然后将替换后的内容保存在特定的templates_c目录下。在运行时还要编译成一个非模板技术的PHP文件,并将其以模板文件名加上“com_”前缀和“.php”的扩展名形式保存。再通过include()函数将处理后的模板文件包含,并使用PHP解析后发送给客户端 使用模板引擎 使用自定义的模板引擎比较容易,都是自己定义的语法格式。但要记住,所有流行的模板引繁解决方案都遵循同样的一组相同的核心实现原则,就是与编程语言一样,学习了一种语言就可以更容易地掌握其他语言。使用模板引擎最主要的原因就是将前端工程师和后端工程师的工作分开,所以模板引擎不仅后端工程师需要使用,前端工程师也需要使用 1、后端工程师对模板引擎的使用 在PHP脚本中包含模板引擎类所在的文件。如下所示: 创建模板引擎类的对象并对一些成员属性进行初始化赋值。如下所示: 将动态数据(包括标量和数组类型的数据,例如从数据库的表中获得的数据数组)使用模板引擎对象中的assign()方法分配给模板文件,这个方法可以使用多次,将任意多个变量分配给模板。如下所示: 在PHP脚本中通过调用模板对象中的display()方法,并将模板文件名作为参数传入,就会加载指定目录中对应的模板文件到PHP脚本中。再通过模板引擎中的替换方法对模板中自定义的语法进行解析,然后输出处理后的模板。如下所示: 2、前端工程师对模板引擎的使用 前端工程师需要将编写的模板文件存放到指定的目录中,这个目录是通过在模板对象中使用$template_dir属性指定的,默认的设置是当前目录下的“templates”目录。另外,模板文件的命名以及后缀名的设置可以随意,例如index.tpl、test.htm、header.tp;等 模板文件是通过使用HTML、CSS以及javascript等Web前台语言以编写的纯静态负而。但可以在模板文件中使用“a2a890d1eab90800994daff8bb7fc69e”两个分隔符中间定义一个变量(类似PHP中的变量格式),该变量可以接受并输出由PHP脚本中分配过来的动态数据。在模板中使用的“a2a890d1eab90800994daff8bb7fc69e”两个分隔符对,也可以根据个人爱好在模板引擎类中修改。如下所示: 姓名:f1ae60a094afb5383c24c6d7d49bae7e,年龄:ffba6e22b13d0326f3e6211269694a5b,性别:1416cefc31bf4e1bc6126908c09b2ed4 //模板中使用占位符 如果在PHP脚本中是将数组分配给模板,也可以在模板中进行遍历,还可以通过嵌套的方式遍历多维数组。使用的是在模板引擎中定义的“180f3c6ca551a35ecefd4b3ba05bd4a5”标记对,使用的方式和PHP中foreach结构的语法格式相似。如下所示: 模板引擎还可以解析在模板文件中使用特殊标记编写的分支结构,语法风格也是和PHP的分支结构类似。是通过在模板文件中使用“45281049cbb9d3b9169f7d17da261b60”标记对实现选择结构,也可以实现多路分支和嵌套分支的选择结构。如下所示: 在自定义的模板引擎中,也添加了在模板文件中包含其他模板文件的功能。可以使用“fe96c9fc2632c177017362ba6ed0e309”标记将子模板包含到当前模板中,还支持在子模板中再次包括另外的子模板。如下所示: 使用示例分析 通过在程序中加载模板引擎可以将前端语言与后端语言的代码分开。首先在PHP程序中获取数据库中存储的数据,再通过加载模板引擎将数据分配出去,然后将模板文件再通过模板引擎加载并处理后输出。所以PHP程序只是创建动态数据,加载模板引擎并将动态数据分配给模板,完成了PHP程序的工作。而模板的设汁也只需要前端工程师独立完成,使用HTML、CSS及javascript等前台页面设计语言编写。另外,在模板文件中还需要使用模板引擎可以解析的标记,将PHP中分配过来的动态数据在模板中引用 1、数据库的设计 假设数据库服务器在“localhost”主机上,连接的用户名和密码分别为“admin”和“123456”,在该服务器上创建一个名为“mydb”的数据库,并在该数据库中创建一个名为“User”的用户表。创建该表的SQL査询语句如下所示: 用户表User创建完成以后,接着可以向该表中插入一些数据作为示例演示使用,SQL查询语句如下所示: 2、模板的设计 模板的设计不要出现任何的PHP代码,可以由前端人员来完成。在自定义的模板引擎中,规定了要到指定的目录中去寻找模板文件,这个特定的目录可以在创建模板引擎对象时指定,也可以使用默认的目录设置,默认可以将模板文件存放在当前目录中的“templates”目录下。本例共需要三个模板文件main.tpl、header.tpl和footer.tpl,都存放在这个默认的目录设置中。这三个模板文件的代码如下所示: 模板的头部文件header.tpl 模板的尾部文件footer.tpl 主模板文件main.tpl 文件main.tpl是主模板文件,在该文件中使用6eaa5ab26c10a3f864f56118cb598a8f和74b967363d8f1808137a4944882c558f两个标记分别在该文件的顶部和底部,将独立的头部和尾部模板文件包含到这个主模板文件中。并在该文件中使用bdced278cc5ac51b4cd270e445a6a1a2标记获取从PHP中动态分配过来的表名,以及使用双层180f3c6ca551a35ecefd4b3ba05bd4a5标记嵌套,遍历从PHP中动态分配过来的在数据库中获取到的二维数组$Users,还在180f3c6ca551a35ecefd4b3ba05bd4a5标记中使用条件选择标记45281049cbb9d3b9169f7d17da261b60组合,将数据中性别为“男”的表格背景设置为红色和一些其他判断。被包含进来的头部模板文件header.tpl和尾部模板文件footer.tpl也同样可以获取从PHP中动态分配给模板的数据 3、PHP程序设计 通过模板引擎的使用,PHP程序员在编写代码时,只需要PHP一种语言就可以了,不用再去使用HTML、CSS以及javascript等页面设计语言完成前端的工作了。下面是一个文件名为index.php的PHP脚本文件,和模板引擎类所在的文件mytpl_class.php在同一个目录下。代码如下所示: 在上面的PHP脚本文件中,通过PDO对象连接MySQL服务器,并获取用户表User中的全部记录,并以PHP的二维数组变量形式保存在变量data中。接着使用包含进来的当前目录下的“mytplclss.php”文件,创建并初始化模板引擎类的对象data中。接着使用包含进来的当前目录下的“mytplclss.php”文件,创建并初始化模板引擎类的对象tpl。再通过该对象中的assign()方法向模板分配一些数据,然后使用该对象中的display()方法载入模板文件main.tpl。并将模板中标记的特殊变量替换为从PHP中分配的动态数据,处理完毕以后输出模板页面。页面的输出结果如下所示 限于各种不同的条件限制,比如时间、经验,做一个自定义的PHP模板引擎是非常困难的。其实,需要的并不是重新构造一个PHP模板,而是选择一个最贴近自己的PHP模板加以改造<?php
/**
file: mytpl.class.php 类名为MyTpl是自定义的模板引擎
通过该类对象加载模板文件并解析,将解析后的结果输出
*/
class Mytpl {
public $template_dir = 'templates'; //定义模板文件存放的目录
public $compile_dir = 'templates_c'; //定义通过模板引擎组合后文件存放目录
public $left_delimiter = '<{'; //在模板中嵌入动态数据变量的左定界符号
public $right_delimiter = '}>'; //在模板中嵌入动态数据变量的右定界符号
private $tpl_vars = array(); //内部使用的临时变量
/**
将PHP中分配的值会保存到成员属性$tpl_vars中,用于将模板中对应的变量进行替换
@param string $tpl_var 需要一个字符串参数作为关联数组下标,要和模板中的变量名对应
@param mixed $value 需要一个标量类型的值,用来分配给模板中变量的值
*/
function assign($tpl_var, $value = null) {
if ($tpl_var != '')
$this->tpl_vars[$tpl_var] = $value;
}
/**
加载指定目录下的模板文件,并将替换后的内容生成组合文件存放到另一个指定目录下
@param string $fileName 提供模板文件的文件名
*/
function display($fileName) {
/* 到指定的目录中寻找模板文件 */
$tplFile = $this->template_dir.'/'.$fileName;
/* 如果需要处理的模板文件不存在,则退出并报告错误 */
if(!file_exists($tplFile)) {
die("模板文件{$tplFile}不存在!");
}
/* 获取组合的模板文件,该文件中的内容都是被替换过的 */
$comFileName = $this->compile_dir."/com_".$fileName.'.php';
/* 判断替换后的文件是否存在或是存在但有改动,都需要重新创建 */
if(!file_exists($comFileName) || filemtime($comFileName) < filemtime($tplFile)) {
/* 调用内部替换模板方法 */
$repContent = $this->tpl_replace(file_get_contents($tplFile));
/* 保存由系统组合后的脚本文件 */
file_put_contents($comFileName, $repContent);
}
/* 包含处理后的模板文件输出给客户端 */
include($comFileName);
}
/**
内部使用的私有方法,使用正则表达式将模板文件'<{ }>'中的语句替换为对应的值或PHP代码
@param string $content 提供从模板文件中读入的全部内容字符串
@return $repContent 返回替换后的字符串
*/
private function tpl_replace($content) {
/* 将左右定界符号中,有影响正则的特殊符号转义 例如,<{ }>转义\<\{ \}\> */
$left = preg_quote($this->left_delimiter, '/');
$right = preg_quote($this->right_delimiter, '/');
/* 匹配模板中各种标识符的正则表达式的模式数组 */
$pattern = array(
/* 匹配模板中变量 ,例如,"<{ $var }>" */
'/'.$left.'\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*'.$right.'/i',
/* 匹配模板中if标识符,例如 "<{ if $col == "sex" }> <{ /if }>" */
'/'.$left.'\s*if\s*(.+?)\s*'.$right.'(.+?)'.$left.'\s*\/if\s*'.$right.'/ies',
/* 匹配elseif标识符, 例如 "<{ elseif $col == "sex" }>" */
'/'.$left.'\s*else\s*if\s*(.+?)\s*'.$right.'/ies',
/* 匹配else标识符, 例如 "<{ else }>" */
'/'.$left.'\s*else\s*'.$right.'/is',
/* 用来匹配模板中的loop标识符,用来遍历数组中的值, 例如 "<{ loop $arrs $value }> <{ /loop}>" */
'/'.$left.'\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*'.$right.'(.+?)'.$left.'\s*\/loop\s*'.$right.'/is',
/* 用来遍历数组中的键和值,例如 "<{ loop $arrs $key => $value }> <{ /loop}>" */
'/'.$left.'\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*=>\s*\$(\S+)\s*'.$right.'(.+?)'.$left.'\s*\/loop \s*'.$right.'/is',
/* 匹配include标识符, 例如,'<{ include "header.html" }>' */
'/'.$left.'\s*include\s+[\"\']?(.+?)[\"\']?\s*'.$right.'/ie'
);
/* 替换从模板中使用正则表达式匹配到的字符串数组 */
$replacement = array(
/* 替换模板中的变量 <?php echo $this->tpl_vars["var"]; */
'<?php echo $this->tpl_vars["${1}"]; ?>',
/* 替换模板中的if字符串 <?php if($col == "sex") { ?> <?php } ?> */
'$this->stripvtags(\'<?php if(${1}) { ?>\',\'${2}<?php } ?>\')',
/* 替换elseif的字符串 <?php } elseif($col == "sex") { ?> */
'$this->stripvtags(\'<?php } elseif(${1}) { ?>\',"")',
/* 替换else的字符串 <?php } else { ?> */
'<?php } else { ?>',
/* 以下两条用来替换模板中的loop标识符为foreach格式 */
'<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"]) { ?>${3}<?php } ?>',
'<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"] => $this->tpl_vars["${3}"]) { ?>${4}<?php } ?>',
/*替换include的字符串*/
'file_get_contents($this->template_dir."/${1}")'
);
/* 使用正则替换函数处理 */
$repContent = preg_replace($pattern, $replacement, $content);
/* 如果还有要替换的标识,递归调用自己再次替换 */
if(preg_match('/'.$left.'([^('.$right.')]{1,})'.$right.'/', $repContent)) {
$repContent = $this->tpl_replace($repContent);
}
/* 返回替换后的字符串 */
return $repContent;
}
/**
内部使用的私有方法,用来将条件语句中使用的变量替换为对应的值
@param string $expr 提供模板中条件语句的开始标记
@param string $statement 提供模板中条件语句的结束标记
@return strin 将处理后的条件语句相连后返回
*/
private function stripvtags($expr, $statement='') {
/* 匹配变量的正则 */
$var_pattern = '/\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*/is';
/* 将变量替换为值 */
$expr = preg_replace($var_pattern, '$this->tpl_vars["${1}"]', $expr);
/* 将开始标记中的引号转义替换 */
$expr = str_replace("\\\"", "\"", $expr);
/* 替换语句体和结束标记中的引号 */
$statement = str_replace("\\\"", "\"", $statement);
/* 将处理后的条件语句相连后返回 */
return $expr.$statement;
}
}
?>
require("mytpl.class.php"); //包含模板引擎类,相当于模板引擎安装
$tpl=new MyTpl(); //创建模板引擎类的对象,也可以根据参数对成员初始化
$tpl->assign("var","this is a value"); //可以分配标量类型数据,可以使用多次
$tpl->assign("arr",array(array(1,2),array("a","b"))); //也可以分配数组包括多维数组
$tpl->display("test.tpl"); //参数“test.tpl”为特定目录下的模板文件
<{loop $arr $value }> //遍历数组$arr中的元素值
数组中的元素值<{$value}> //每次遍历输出元素中的值
<{/loop}> //在模板中遍历数组的结束标记
<{loop $arr $key=>$value }> //遍历数组$arr中的元素下标和元素值
数组中的元素键<{$key}> //每次遍历输出元素中的下标
数组中的元素值<{$value}> //每次遍历输出元素中的值
<{/loop}> //在模板中遍历数组的结束标记
<{loop $arr $value }> //遍历数组$arr中的元素值
<{loop $arr $data }> //使用嵌套标记遍历二维数组
数组中的元素值<{$value}> //每次遍历输出元素中的值
<{/loop}> //在模板中遍历数组的内层结束标记
<{/loop}> //在模板中遍历数组的外层结束标记
<{if($var=="red")}>
<p style="color:red">这是“红色”的字</p>
<{elseif($var=="green")}>
<p style="color:green">这是“绿色”的字</p>
<{else}>
<{if($size=20)}>
<p style="font-size:20">这是“20px”大小的字</p>
<{/if}>
<{/if}>
<{include 'other.tpl' }>
CREATE TABLE User(
id SMALLINT(3) NOT NULL AUTO_INCREMENT,
name VARCHAR(10) NOT NULL DEFAULT '',
sex VARCHAR(4) NOT NULL DEFAULT '',
age SMALLINT(2) NOT NULL DEFAULT '0',
email VARCHAR(20) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
INSERT INTO User (name,sex,age,email) VALUES
("a","男",27,"a@a.com"),
("b","女",22,"b@b.com"),
("c","女",30,"c@c.com"),
("d","女",24,d@d.com);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> <{$title}> </title>
</head>
<body>
<p style="width:200px;margin: 0 auto;">##### <{$author}> #####</p>
</body>
</html>
<{include 'header.tpl'}>
<table border="1" align="center" width="500">
<{ loop $users $user }>
<tr>
<{loop $user $u }>
<{if $u == "男" }>
<td style="color:green">
<{elseif $u == "女"}>
<td style="color:red">
<{else}>
<td>
<{/if}>
<{$u}></td>
<{/loop}>
</tr>
<{/loop}>
</table>
<{include 'footer.tpl'}>
<?php
//包含模板引擎类
include "mytpl.class.php";
//创建模板引擎对象
$tpl = new Mytpl;
//连接数据库
$pdo = new PDO("mysql:host=localhost;dbname=mydb", "admin", "123456");
//执行SQL语句
$stmt = $pdo -> prepare("select id, name, sex,age,email from User order by id");
$stmt ->execute();
$data = $stmt -> fetchAll(PDO::FETCH_ASSOC);
//这是从数据库获取的动态数据,需要在模板中显示
$tpl->assign('title',"自定义模板引擎");$tpl->assign('auto',"小火柴");
$tpl->assign('users',$data);
$tpl -> display("main.tpl");
?>
The above is the detailed content of Sample code sharing for PHP's custom template engine. For more information, please follow other related articles on the PHP Chinese website!