ホームページ >バックエンド開発 >PHPチュートリアル >簡単なPHPテンプレートエンジンを自分で書く
自己动手写一个简单的php模板引擎
模板引擎中最核心的思想是:将模板中的变量编译为php的变量进行输出。
例如:demo.tpl
{$data} {$title}
那么模板引擎就要将{$data} {$title} 编译为
要实现这个功能使用正则替换就可以了:
$content = '{$data}{$title}'; $pattern = "/\{\\$([a-zA-Z_][a-zA-Z0-9_]*)\}/"; $content = preg_replace($pattern,'<?php echo \$this->tmpValue["$1"] ?>',$content); echo $content; // <?php echo $data; ?><?php echo $title; ?>
首先是tempTool.class.php 它的作用的提供模板引擎需要用到的一些小工具
<?php /** * 工具类 **/ class tempTool { protected $error = array(); //错误信息 function __construct() { } /** * 生成错误日志数组 **/ protected function error($k,$v) { if(!empty($k) && !empty($v)) { $this->error[$k] = $v; }else { exit('tempTool.class.php的error方法收到了不确定的参数错误!'); } } /** * 获取错误信息 **/ public function getError() { foreach($this->error as $k=>$v) { echo $k.$v.'<br />'; } } } ?>
然后是template.class.php 它的作用是提供模板引擎应该有的功能
<?php /** * 模板引擎类 用语提供模板引擎应该具有的方法 **/ include_once "tempTool.class.php"; class template extends tempTool{ private $config = array( 'tmpDir'=>'template/', // 模板文件目录 'cmpDir'=>'compile/', // 编译文件目录 'cacheDir'=>'cache/', // 缓存文件目录 'tmpSuffix' =>'.tpl', // 模板文件后缀 'cacheSuffix' =>'.html', // 缓存文件后缀 'caching' =>false // 是否开启缓存 ); private $tmpFile; // 模板文件 private $cmpFile; // 编译文件 private $cacheFile; // 缓存文件 private $tmpValue = array(); // 变量值栈 public function __construct($config = null) { // 同步配置 if(is_array($config)) { $this->config = array_merge($this->config,$config); } // 检查模板编译缓存目录是否存在不存在创建 if( !$this->checkDir($this->config['tmpDir']) || !$this->checkDir($this->config['cmpDir']) || !$this->checkDir($this->config['cacheDir']) ) { exit; } } /** * 检查目录是否存在不存在自动创建 **/ private function checkDir($dir) { if(!is_dir($dir)) { if(!mkdir($dir)) { $this->errorLog[] = array('创建文件夹失败:'=>$dir); return false; } } return true; } /** * 像模板中分配变量 * **/ public function assign($k,$v) { if(!empty($k) && !empty($v)) { $this->tmpValue[$k] = $v; }else { $this->error('分配变量失败:','分配到模板中变量的key或者value为空!'); } } /** * 编译文件 **/ public function display($tmpFile) { // 获取模板文件 $tmpFile = $this->config['tmpDir'].$tmpFile.$this->config['tmpSuffix']; // 获取编译文件 $cmpFile = $this->config['cmpDir'].md5($tmpFile.'compile').'.php'; if(!file_exists($tmpFile)) { $this->error('模板文件不存在:',$tmpFile.'不存在'); } // 当编译文件不存在或者是模板文件被修改过了才重新编译 if(!file_exists($cmpFile) || filemtime($cmpFile) < filemtime($tmpFile)) { include_once "compile.class.php"; $cmp = new compile(); $cmp->cmp($tmpFile,$cmpFile); } // 是否开启缓存 if($this->config['caching']) { // 获取缓存文件 $cacheFile = $this->config['cacheDir'].md5($tmpFile.'cache').$this->config['cacheSuffix']; // 当缓存文件不存在或者是模板文件被修改过重新生成缓存文件 if(!file_exists($cacheFile) || filemtime($cacheFile) < filemtime($tmpFile)) { ob_start(); include_once $cmpFile; $content = ob_get_clean(); if(!file_put_contents($cacheFile,$content)){ $this->error('编译文件生成失败:',$cacheFile); } } //载入缓存文件 include $cacheFile; }else { // 载入编译文件 include_once $cmpFile; } } }
compile.class.php 编译类将模板文件编译为php文件
<?php /** * 编译类将模板文件编译为php文件 **/ include_once "tempTool.class.php"; class compile extends tempTool { private $content; // 文件编译后的内容 /** * 将模板文件编译php文件 **/ function cmp($tmpFile,$cmpFile) { if(!($content = file_get_contents($tmpFile))){ $this->error("文件读取失败:",$tmpFile); } $pattern = "/\{\\$([a-zA-Z_][a-zA-Z0-9_]*)\}/"; $this->content = preg_replace($pattern,'<?php echo \$this->tmpValue["$1"] ?>',$content); $this->parse($cmpFile); } /** * 将编译好的内容写入文件 **/ public function parse($cmpFile) { if(!file_put_contents($cmpFile,$this->content)){ $this->error('文件写入失败:',$cmpFile); } } } ?>
1. 新建一个 template 文件夹 在里面写 一个模板 demo.tpl
{$data} {$title}2.新建一个demo.php
<?php $config = array('caching'=>true); include_once "template.class.php"; $tmp = new template($config); $tmp->assign('data','ccc'); $tmp->assign('title','这时测试用例'); $tmp->display('demo');
可以看一下cache目录和 compile目录下 会生成一个缓存文件 和一个编译文件
这时就成功了