模板引擎-实现
1.目录结构
Project
|-view
| |-page.html
| |-show.html
|-cache
|-Tpl.php
|-index.php
view
存放 HTML模板文件
cache
存放由 HTML模板文件 生成的 PHP缓存文件
Tpl.php
模板引擎类,用于将 HTML模板文件 中的 {模板语句} 替换为 <?=PHP语句;?>,并在 cache文件夹 生成 PHP缓存文件,然后包含 PHP缓存文件 以显示出来
index.php
利用 模板引擎类 显示页面
2.代码实现
访问 index.php 时,将通过 Tpl.php 中的 模板引擎类 在 cache文件夹 中生成 page.html.php 和 show.html.php,并包含它们将内容显示出来
index.php
<?php
include 'Tpl.php';
$tpl = new Tpl();
// 设置变量
$tpl->assign('title', 'title');
$tpl->assign('show', 'HI,HACKER!');
$tpl->assign('data', ['HACK', 'ME']);
// 显示页面
$tpl->display('page.html', true);
Tpl.php
<?php
class Tpl {
// HTML模板文件的路径
protected $viewDir = './view/';
// 生成的PHP缓存文件的路径
protected $cacheDir = './cache/';
// PHP缓存文件的过期时间
protected $lifetime = 3600;
// 存放变量的数组
protected $vars = [];
// 存放变量
function assign($name, $value) {
$this->vars[$name] = $value;
}
/*
* 显示PHP缓存文件
* 参数1:HTML模板文件名
* 参数2:HTML模板文件是否需要包含
*/
function display($viewName, $isInclude) {
// 模板文件全路径
$viewPath = $this->viewDir.$viewName;
// 缓存文件全路径
$cahePath = $this->cacheDir.$viewName.'.php';
// PHP缓存文件不存在则生成PHP缓存文件
if (!file_exists($cahePath)) {
$php = $this->compile($viewPath);
file_put_contents($cahePath, $php);
}
// PHP缓存文件超时则需要重新生成PHP缓存文件
else {
$isTimeout = (filectime($cahePath) + $this->lifetime) > time() ? false : true;
if ($isTimeout) {
$php = $this->compile($viewPath);
file_put_contents($cahePath, $php);
}
}
// 需要包含则解析变量并包含PHP缓存文件
if ($isInclude) {
extract($this->vars);
include $cahePath;
}
}
// 生成PHP缓存文件
protected function compile($viewPath) {
// 获取HTML模板文件内容
$html = file_get_contents($viewPath);
// \1为第一个捕获组匹配到的内容
$array = [
'{$%%}'=>'<?=$\1;?>',
'{foreach %%}'=>'<?php foreach (\1):?>',
'{/foreach}'=>'<?php endforeach;?>',
'{include %%}'=>''
];
foreach ($array as $key=>$value) {
/*
* 转义并生成正则
* #包裹表示正则的/不需要转义
* (.+?)表示一个懒惰匹配的捕获组
*/
$pattern = '#'.str_replace('%%', '(.+?)', preg_quote($key)).'#';
// 对HTML模板文件内容进行正则替换,include特殊情况要用回调函数处理
if (strstr($pattern, 'include')) {
$html = preg_replace_callback($pattern, [$this, 'parseInclude'], $html);
}
else {
$html = preg_replace($pattern, $value, $html);
}
}
return $html;
}
// 处理include,生成要包含进来的HTML模板文件的PHP缓存文件
protected function parseInclude($data) {
/*
* 生成要包含进来的HTML模板文件的PHP缓存文件
* $data[0]为匹配到的{include show.html}
* $data[1]为第一个捕获组匹配到的show.html
*/
$this->display($data[1], false);
$cachePath = $this->cacheDir.$data[1].'.php';
return '<?php include "'.$cachePath.'";?>';
}
}
page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{$title}</title>
</head>
<body>
{include show.html}
{foreach $data as $value}
{$value}<br>
{/foreach}
</body>
</html>
show.html
<div>{$show}</div>