模板引擎作為視圖層和模型曾分離的一種解決方案。
首先我們新建一個Template.class.php 的文件
<?php
class Template{
private $arrayConfig = array(
'suffix' => '.m', //設(shè)置模板文件
'templateDir' => 'template/', //設(shè)置模板所在的文件夾
'compileDir' => 'cache',
'debug' => false, //設(shè)置編譯后存放的目錄
'cache_htm' => true, //是否需要編譯成靜態(tài)的html文件
'suffix_cache'=> '.htm', //編譯后的文件后綴
'cache_time' =>2000, // 多長時間自動更新
'php_turn' =>false, //是否支持原生的php代碼
'cache_control' => 'control.dat',
);
private $compileTool; //編譯器
public $filename; //模板文件名稱
private $value =array(); //值棧
static private $instance = null;
public $debug = array(); //調(diào)試信息
public function __construct($arrayConfig =array()){
//返回當(dāng)前UNIX時間戳和微妙數(shù)
$this->debug['begin'] = microtime(true);
$this->arrayConfig =$arrayConfig+$this->arrayConfig;
$this->getPath();
if(!is_dir($this->arrayConfig['templateDir'])){
exit("template isnt not found");
}
if(!is_dir($this->arrayConfig['compileDir'])){
mkdir($this->arrayConfig['compileDir'],0770,true);
}
include("Compile.class.php");
//$this->compileTool = new Compile;
}
/**
路徑處理為絕對路徑
*/
public function getPath(){
$this->arrayConfig['templateDir'] = strtr(realpath($this->arrayConfig['templateDir']),'\\','/').'/';
$this->arrayConfig['compileDir'] = strtr(realpath($this->arrayConfig['compileDir']),'\\','/').'/';
}
/***
單例模式獲取模板的實例
**/
public static function getInstance(){
if(is_null(self::$instance)){
self::$instance = new Template();
}
return self::$instance;
}
public function setConfig($key,$value = null){
if(is_array($key)){
$this->arrayConfig = $key+$this->arrayConfig;
}else{
$this->arrayConfig[$key] = $value;
}
}
public function getConfig($key = null){
if($key){
return $this->arrayConfig[$key];
}else{
return $this->arrayConfig;
}
}
/**
注入單個變量
**/
public function assign($key,$value){
$this->value[$key] = $value;
}
/**
注入多個變量
**/
public function assignArray($array){
if(is_array($array)){
foreach($array as $k => $v){
$this->value[$k] = $v;
}
}
}
/***
獲取模板文件的路徑
**/
public function path(){
return $this->arrayConfig['templateDir'].$this->filename.$this->arrayConfig['suffix'];
}
/***
是否需要緩存
**/
public function needCache(){
return $this->arrayConfig['cache_htm'];
}
/***
是否需要重新生成緩存文件
**/
public function reCache($file){
$flag = false;
//生成緩存文件
$cacheFile = $this->arrayConfig['compileDir'].md5(@$filename).'.'.'php';
//var_dump($cacheFile);
if($this->arrayConfig['cache_htm']===true){
//設(shè)置timeflag (判斷當(dāng)前時間-模板文件上次修改的時間)是否小于設(shè)置的緩存時間
//如果小于則返回TRUE
$timeFlag = (time()-@filemtime($cacheFile))<$this->arrayConfig['cache_time']?
true:false;
//1,,判斷緩存文件是否存在,,
//2,,緩存文件是否有內(nèi)容
//3,,時間是否在設(shè)置的緩存時間之內(nèi)
if(!is_file($cacheFile)&&filesize($cacheFile)>1&&$timeFlag){
$flag = true;
}else{
$flag = false;
}
}
return $flag;
}
/***
顯示模板
**/
public function show($file){
$this->filename =$file;
if(!is_file($this->path())){
exit('找不到相對應(yīng)的模板');
}
$compileFile = $this->arrayConfig['compileDir'].'/'.md5(@$filename).'.php';
$cacheFile = $this->arrayConfig['compileDir'].md5(@$filename).'.htm';
// echo $compileFile;
//echo $cacheFile;
if($this->reCache($file)===false){
$this->debug['cached'] = 'false';
// var_dump($compileFile);
$this->compileTool = new Compile($this->path(),$compileFile,$this->arrayConfig);
if($this->needCache()){
//是否需要緩存
ob_start();
}
//函數(shù)從數(shù)組中把變量導(dǎo)入到當(dāng)前的符號表中
extract($this->value,EXTR_OVERWRITE);
//判斷 文件是否存在,生成文件的修改時間是否小于模板文件修改時間
if(@is_file($compileFile)||filemtime($compileFile)<filemtime($this->path())){
$this->compileTool->vars = $this->value;
$this->compileTool->compile();
//引入文件
include $compileFile;
}else{
include $compileFile;
}
if($this->needCache()){
//如果需要緩存的話
$message = ob_get_contents();
//則生成緩存文件
file_put_contents($cacheFile,$message);
}
}else{
//如果緩存文件時間小于設(shè)定的時間
//直接讀取緩存文件
readfile($cacheFile);
//$this->debug['cached'] = true;
}
$this->debug['spend'] = microtime(true) - $this->debug['begin'];
$this->debug['count'] = count($this->value);
$this->debug_info();
/*
var_dump($compileFile);this
var_dump($this->path());
if(!is_file($compileFile)){
mkdir($this->arrayConfig['compileDir']); // 此處若存在需要判斷
$this->compileTool->compile($this->path(),$compileFile);
readfile($compileFile);
}else{
readfile($compileFile);
}
*/
}
/***
debug 調(diào)試函數(shù)
**/
public function debug_info(){
//$this->arrayConfig['debug']=false;
if($this->arrayConfig['debug']===true){
var_dump($this);
echo "程序運行日期",date("Y-m-d h:i:s")."</br>";
echo "模板解析耗時",$this->debug['spend'],'秒'."</br>";
echo "模板包含標(biāo)簽數(shù)目",$this->debug['count']."</br>";
echo "是否使用靜態(tài)緩存",$this->debug['cached']."</br>";
//echo "模板引擎實例參數(shù)",var_dump($this->getConfig());
}
}
/******
清楚緩存的文件
*****/
public function clean($path = null){
if($path = null){
$path = $this->arrayConfig['CompileDir'];
$path = glob($path.'*'.$this->arrayConfig['suffix_cache']);
//glob 函數(shù)返回匹配指定的文件夾目錄
}else{
$path = $this->arrayConfig['compileDir'].md5($path).'.htm';
foreach((array)$path as $v){
//刪除
unlink($v);
}
}
}
}
新建一個 Compile.class.php 翻譯模板文件
<?php
class Compile{
private $template; //待編譯的文件
private $content; //需要替換的文本
private $comfile; //編譯后的 文件
private $left = '{';
private $right = '}';
private $value =array(); // 值棧
private $phpTurn;
private $T_P = array();
private $T_R = array();
public function __construct($template,$compileFile,$config){
//echo $template;
//echo $compileFile;
$this->template = $template;
$this->comfile = $compileFile;
$this->content = file_get_contents($template);
if($config['php_turn']===false){
//echo "123";
//$this->T_R[]="";
}
//echo "123";
//正則匹配 {$xxx} 格式
$this->T_P[]="#\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}#";
$this->T_R[]="<?php echo \$this->value['\\1'];?>";
}
public function compile(){
$this->c_var2();
//$this->c_staticFile();
//var_dump($this);
file_put_contents($this->comfile,$this->content);
}
public function c_var2(){
// 將{$xxx} 替換為<?php echo $xxx?>
$this->content = preg_replace($this->T_P,$this->T_R,$this->content);
}
public function c_staticFile(){
$this->content =preg_replace('#\{\!(.*?)\!\}#','<script src =\\1'.'?t='.time().'></script>',$this->content);
}
public function __set($name,$value){
$this->$name = $value;
}
public function __get($name){
return $this->$name;
}
}
新建一個測試文件 test.php
<?php
include "Template.class.php";
$tpl = Template::getInstance();
//$tpl = new Template(array('php_turn'=>false,'debug'=>false));
$tpl->assign('data','hello world');
$tpl->show('member');
//var_dump($tpl->getConfig());
模板文件member.m
<html>
<head></head>
<body>
<h1>welcome</h1>
</body>
{$data}
</html>
顯示截圖
借鑒 php核心技術(shù)與最佳實踐