在进入正题之前先明确几个关键点,有助于帮助我们理解这个PHP模板引擎产生的原因.
为了能够让表现层和逻辑层分离,方便将来修改前台界面的时候不会改动的逻辑层的逻辑.
一个好的模板引擎需要具备哪些素质:
能够很好的把表现层和逻辑层分离
不可以影响前台的访问浏览速度
使用简单
参数对比:
现在市面上PHP的模板引擎不计其数,基本上每个模板引擎都能实现逻辑层和表现层的分离,那么接下来我们需要考虑的就是方便使用和解析速度的问题了.
首先我们看速度方面,目前市面上速度最快的模板引擎应该就是smarty(其他那些模板引擎的速度不敢恭维,抛开不谈),但是他臃肿,他有一套属于他自己的模板语言,对于每一个使用者来说都要学会他的模板语言才能够正常使用,这一点来讲它在使用简单方面就没有任何的优势,因此针对以上问题我制作了自己的模板引擎,即您即将看到的超级模板引擎.
模板引擎类的核心代码如下:
<?php
/**
* Copyright (c) 2010-10-13 F. seven (See7di@Gmail.Com)
*/
Class Template{
var $vars; // 用來保存所有的模板變量
var $path; // 模板文件存放的路徑,必須/結束
var $debug; // 是否开启调试模式
var $expire;
var $cached;
var $cacheid;
/* 構造函數
* @參數 (string) $path 模板文件的路徑
* @參數 (int) $expire 緩存的有效期(秒)
* @返回 (null)
*/
Function Template($expire=900,$debug=False,$path="./tpl/"){
$this->path = $path;
$this->vars = array();
$this->debug = $debug;
$this->expire = $expire;
//根据逻辑层文件的md5值计算cacheid,可防止产生垃圾缓存
$this->cacheid = 'cache/'.Md5_file(Realpath("./").Basename($_SERVER["PHP_SELF"]));
}
// 重新設置模板文件存放路徑
Function setPath($path){
$this->path = $path;
}
/*
* 設置模板內使用的變量
* @參數 (string) $name 需要設置的變量名
* @參數 (mixed) $value 該變量的值
* @返回 (null)
*/
Function set($name, $value){
$this->vars[$name] = $value;
}
/*
* 将模板变量合并或重写存放到一个数组内
* @參數 (array) $vars 待操作數組名
* @參數 (bool) $clear 是否允許重寫已存在的變量
* @返回 (null)
*/
Function setVar($vars, $clear = False){
IF($clear){
$this->vars = $vars;
}Else{
IF(Is_array($vars)){
$this->vars = Array_merge($this->vars, $vars);
$this->vars = $this->FormatKey($this->vars);
}
}
}
/*
* 将数字索引的数组键值修改成符合变量标准的键值
* @例子 Array("a"=>"a","b",3=>"c")转换之后是Array("a"=>"aa","_0"=>"b","_3"=>"c")
* @參數 (array) 待格式化的数组
* @返回 (array)
*/
Function FormatKey($arr){
$_keys=Array_keys($arr);
Foreach($_keys as $key=>$value){
IF(Is_numeric($value)){
$_keys[$key]="_".$value;
}
}
Return Array_combine($_keys,$arr);
}
/*
* 根據cacheid判斷當前的緩存是否有效
* @返回 (bool)
*/
Function Is_cached(){
IF($this->cached){Return True;}
IF(!$this->cacheid){Return False;}
IF(!File_exists($this->cacheid)){Return False;}
IF(!($mtime = Filemtime($this->cacheid))){Return False;}
// 緩存是否已過期?
IF(($mtime + $this->expire) < time()){
@Unlink($this->cacheid);
Return False;
}Else{
$this->cached = True;
Return True;
}
}
/*
* 打開,解析,并返回模板文件
* @參數 (string) 模板文件名
* @返回 (string)
*/
Function Fetch($file){
IF(!File_Exists($this->path . $file)){Return False;}
Extract($this->vars); // 提取變量到當前命名空間
OB_start(); // 開始輸出緩沖
OB_clean(); // 清理原有內容
Include($this->path . $file); // 調用模板文件
$contents = ob_get_contents(); // 取得緩存區內容
ob_end_clean(); // 結束緩沖區
Return $contents; // 返回模板文件執行結果后的內容
}
/*
* 根據cacheid返回被緩存的內容,如果尚未緩存則馬上緩存
* @參數 (string) $file 模板文件名
* @返回 (string)
*/
Function FetchCache($file){
IF($this->Is_cached()){
IF($this->debug){Echo "<br>{直接读缓存}<br>";}
$fp = @Fopen($this->cacheid, 'r');
$contents = fread($fp, Filesize($this->cacheid));
Fclose($fp);
Return $contents;
}Else{
IF($this->debug){Echo "<br>{写入并返回缓存}<br>";}
$contents = $this->Fetch($file);
IF($fp = @Fopen($this->cacheid, 'w')){
Fwrite($fp, $contents);
Fclose($fp);
}Else{
Die('Unable to write cache.');
}
Return $contents;
}
}
}
?>
模板引擎的实例化:
<?php
//注意:一旦手工修改过实例化文件后最好是删掉所有缓存文件,让其重新缓存一次
Require_once('Template.php');
$tpl = &New Template();
$tpl->set('title', 'User Profile');
$arr = Array();
$arr = Array(
"a"=>1,
"b"=>"b",
"c"=>array(12,23)
);
$arr["d"]=array("第一个","第二个");
For($i=0;$i<10;$i++){
$arr[$i]="值{$i}";
}
$tpl->setVar($arr);
//echo $tpl->fetch('tpl1.php');
Echo $tpl->fetchCache('tpl1.php');
?>
模板是这样的:
相关的模板是这样的:<br>
<table cellpadding="3" border="0" cellspacing="1">
<tr>
<td><a href='1.php' title=''>1.php</a></td>
<td><a href='index.php' title=''>index.php</a></td>
</tr>
<tr>
<td>键值A:</td>
<td><?=$a;?></td>
</tr>
<tr>
<td>键值B:</td>
<td><?=$b;?></td>
</tr>
<tr>
<td>键值C:</td>
<td><?PHP
For($i=0;$i<count($c);$i++){
Echo $c[$i]."<br>";
}
?></td>
</tr>
<tr>
<td>键值D:</td>
<td><?PHP
For($i=0;$i<count($d);$i++){
Echo $d[$i]."<br>";
}
?></td>
</tr>
<tr>
<td>后期扩展的</td>
<td><?PHP
For($i=0;$i<10;$i++){
Echo ${"_".$i}."<br>";
}
?></td>
</tr>
</table>
我为什么要这样做呢?
因为我认为PHP的循环比任何模板引擎里边的模板语言循环更简单且更容易理解,这一点对于制作前台表现的美工来说并不难学习,而对于那些原来就懂得PHP程序编写的程序员来说简直就是手到擒来,根本就不需要再学习一门新的模板语言.既然如此何乐而不为呢?
另外这样的模板引擎速度比市面上速度最快的模板引擎smarty速度更是快了很多倍,以循环10000次做测试,仅仅比直接使用PHP的echo输出慢接近8毫秒,既然是10000次慢8毫秒,那么这完全可以忽略不计.
因为他使用简单,外加速度非常快,所以就叫他"超级模板引擎"吧!
//如果要轉載本文請注明出處,免的出現版權紛爭,我不喜歡看到那種轉載了我的作品卻不注明出處的人 Seven{See7di#Gmail.com}
什么是PHP模板引擎:为了能够让表现层和逻辑层分离,方便将来修改前台界面的时候不会改动的逻辑层的逻辑.
一个好的模板引擎需要具备哪些素质:
能够很好的把表现层和逻辑层分离
不可以影响前台的访问浏览速度
使用简单
参数对比:
现在市面上PHP的模板引擎不计其数,基本上每个模板引擎都能实现逻辑层和表现层的分离,那么接下来我们需要考虑的就是方便使用和解析速度的问题了.
首先我们看速度方面,目前市面上速度最快的模板引擎应该就是smarty(其他那些模板引擎的速度不敢恭维,抛开不谈),但是他臃肿,他有一套属于他自己的模板语言,对于每一个使用者来说都要学会他的模板语言才能够正常使用,这一点来讲它在使用简单方面就没有任何的优势,因此针对以上问题我制作了自己的模板引擎,即您即将看到的超级模板引擎.
模板引擎类的核心代码如下:
<?php
/**
* Copyright (c) 2010-10-13 F. seven (See7di@Gmail.Com)
*/
Class Template{
var $vars; // 用來保存所有的模板變量
var $path; // 模板文件存放的路徑,必須/結束
var $debug; // 是否开启调试模式
var $expire;
var $cached;
var $cacheid;
/* 構造函數
* @參數 (string) $path 模板文件的路徑
* @參數 (int) $expire 緩存的有效期(秒)
* @返回 (null)
*/
Function Template($expire=900,$debug=False,$path="./tpl/"){
$this->path = $path;
$this->vars = array();
$this->debug = $debug;
$this->expire = $expire;
//根据逻辑层文件的md5值计算cacheid,可防止产生垃圾缓存
$this->cacheid = 'cache/'.Md5_file(Realpath("./").Basename($_SERVER["PHP_SELF"]));
}
// 重新設置模板文件存放路徑
Function setPath($path){
$this->path = $path;
}
/*
* 設置模板內使用的變量
* @參數 (string) $name 需要設置的變量名
* @參數 (mixed) $value 該變量的值
* @返回 (null)
*/
Function set($name, $value){
$this->vars[$name] = $value;
}
/*
* 将模板变量合并或重写存放到一个数组内
* @參數 (array) $vars 待操作數組名
* @參數 (bool) $clear 是否允許重寫已存在的變量
* @返回 (null)
*/
Function setVar($vars, $clear = False){
IF($clear){
$this->vars = $vars;
}Else{
IF(Is_array($vars)){
$this->vars = Array_merge($this->vars, $vars);
$this->vars = $this->FormatKey($this->vars);
}
}
}
/*
* 将数字索引的数组键值修改成符合变量标准的键值
* @例子 Array("a"=>"a","b",3=>"c")转换之后是Array("a"=>"aa","_0"=>"b","_3"=>"c")
* @參數 (array) 待格式化的数组
* @返回 (array)
*/
Function FormatKey($arr){
$_keys=Array_keys($arr);
Foreach($_keys as $key=>$value){
IF(Is_numeric($value)){
$_keys[$key]="_".$value;
}
}
Return Array_combine($_keys,$arr);
}
/*
* 根據cacheid判斷當前的緩存是否有效
* @返回 (bool)
*/
Function Is_cached(){
IF($this->cached){Return True;}
IF(!$this->cacheid){Return False;}
IF(!File_exists($this->cacheid)){Return False;}
IF(!($mtime = Filemtime($this->cacheid))){Return False;}
// 緩存是否已過期?
IF(($mtime + $this->expire) < time()){
@Unlink($this->cacheid);
Return False;
}Else{
$this->cached = True;
Return True;
}
}
/*
* 打開,解析,并返回模板文件
* @參數 (string) 模板文件名
* @返回 (string)
*/
Function Fetch($file){
IF(!File_Exists($this->path . $file)){Return False;}
Extract($this->vars); // 提取變量到當前命名空間
OB_start(); // 開始輸出緩沖
OB_clean(); // 清理原有內容
Include($this->path . $file); // 調用模板文件
$contents = ob_get_contents(); // 取得緩存區內容
ob_end_clean(); // 結束緩沖區
Return $contents; // 返回模板文件執行結果后的內容
}
/*
* 根據cacheid返回被緩存的內容,如果尚未緩存則馬上緩存
* @參數 (string) $file 模板文件名
* @返回 (string)
*/
Function FetchCache($file){
IF($this->Is_cached()){
IF($this->debug){Echo "<br>{直接读缓存}<br>";}
$fp = @Fopen($this->cacheid, 'r');
$contents = fread($fp, Filesize($this->cacheid));
Fclose($fp);
Return $contents;
}Else{
IF($this->debug){Echo "<br>{写入并返回缓存}<br>";}
$contents = $this->Fetch($file);
IF($fp = @Fopen($this->cacheid, 'w')){
Fwrite($fp, $contents);
Fclose($fp);
}Else{
Die('Unable to write cache.');
}
Return $contents;
}
}
}
?>
模板引擎的实例化:
<?php
//注意:一旦手工修改过实例化文件后最好是删掉所有缓存文件,让其重新缓存一次
Require_once('Template.php');
$tpl = &New Template();
$tpl->set('title', 'User Profile');
$arr = Array();
$arr = Array(
"a"=>1,
"b"=>"b",
"c"=>array(12,23)
);
$arr["d"]=array("第一个","第二个");
For($i=0;$i<10;$i++){
$arr[$i]="值{$i}";
}
$tpl->setVar($arr);
//echo $tpl->fetch('tpl1.php');
Echo $tpl->fetchCache('tpl1.php');
?>
模板是这样的:
相关的模板是这样的:<br>
<table cellpadding="3" border="0" cellspacing="1">
<tr>
<td><a href='1.php' title=''>1.php</a></td>
<td><a href='index.php' title=''>index.php</a></td>
</tr>
<tr>
<td>键值A:</td>
<td><?=$a;?></td>
</tr>
<tr>
<td>键值B:</td>
<td><?=$b;?></td>
</tr>
<tr>
<td>键值C:</td>
<td><?PHP
For($i=0;$i<count($c);$i++){
Echo $c[$i]."<br>";
}
?></td>
</tr>
<tr>
<td>键值D:</td>
<td><?PHP
For($i=0;$i<count($d);$i++){
Echo $d[$i]."<br>";
}
?></td>
</tr>
<tr>
<td>后期扩展的</td>
<td><?PHP
For($i=0;$i<10;$i++){
Echo ${"_".$i}."<br>";
}
?></td>
</tr>
</table>
我为什么要这样做呢?
因为我认为PHP的循环比任何模板引擎里边的模板语言循环更简单且更容易理解,这一点对于制作前台表现的美工来说并不难学习,而对于那些原来就懂得PHP程序编写的程序员来说简直就是手到擒来,根本就不需要再学习一门新的模板语言.既然如此何乐而不为呢?
另外这样的模板引擎速度比市面上速度最快的模板引擎smarty速度更是快了很多倍,以循环10000次做测试,仅仅比直接使用PHP的echo输出慢接近8毫秒,既然是10000次慢8毫秒,那么这完全可以忽略不计.
因为他使用简单,外加速度非常快,所以就叫他"超级模板引擎"吧!