首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

收藏此问题 发表新评论

毛毛虫教你写一个属于自己的模板引擎(更新完毕)

#phpchina首发#

Smarty一直被人视为是多余的东西,我觉得认为Smarty多余的人才是多余的....不说这些了。今天我就教大家写个模板引擎,让大家都可以写一个属于自己的模板引擎,而且看完这篇文章之后,你对Smarty的认识会更进一步的。我的模板引擎名叫Stupid("傻瓜"的意思),我不喜欢太聪明的东西!
Stupid模板引擎是由3个文件组成,他们分别是:stupid.class.php,stupid_parser.class.php,stupid_debugger.class.php。
Stupid.class.php的任务是设置变量,模板路径,和显示等功能,而stupid_parser.class.php就是编译模板文件的,stupid_debugger.class.php是用来调试用的。


好了,我们现在就先编写stupid.class.php吧。
1.新建一个PHP文件名为:stupid.class.php。
我们的类叫Stupid,我们先设计一下成员变量吧。
成员变量有:$_tpl_vars, $_tpl_file, $_parser, $_debugger;
$_tpl_vars: 用来保存模板变量的;
$_tpl_file: 用来保存模板文件名的;
$_parser: 保存StupidParser对象的,就是编译对象;
$_debugger: 保存StupidDebug对象的,就是调试对象;

下面定义了两个常量,用来存放模板文件夹和编译文件夹的:
define('TPL_DIR', './templates/');
define('TPL_C_DIR', './templates_c/');

开始编码了>>>

<?php
define('TPL_DIR', './templates/');
define('TPL_C_DIR', './templates_c/');

class Stupid {
        private $_tpl_vars;
        private $_tpl_file;
        private $_parser;
        private $_debugger;
}
?>


开始写个构造器吧>>>

public function Stupid() {
  if(!is_dir(TPL_DIR) || !is_dir(TPL_C_DIR)) {
   exit('错误:请正确设置模板文件夹和编译文件夹');
  }
}

在构造器中,我们判断了模板路径和编译路径是否设置正确.

设计我们的方法
我们这个类中主要有以下方法:
assign(), set_tpl_dir(), set_parsed_dir(), display(), debug().
assign()方法:
assign()的用处是设置模板变量.代码如下>>>
[php]
public function assign($var, $value) {
if(isset($var) && trim($var) != '') {
                $this->_tpl_vars[$var] = $value;
                return true;
        } else {
                exit('错误:请设置变量名');
        }
}
[/php]

我们先判断用户是否设置了变量名,用isset($var) && trim($var) != ''来判断, trim($var) != ''是防止用户以空格来设置变量名.如果设置变量正确,我们就将他保存到成员变量_tpl_vars中.

display()方法
display()方法是Stupid类中最重要的方法,他是用来显示和检测模板是否更新了,更新了就再编译,没有更新就用原来编译之后的文件.

代码如下>>>

public function display($tpl_file) {
  $template_file = TPL_DIR.$tpl_file;
  if(!file_exists($template_file)) {
   exit('错误:模板文件不存在');
  }
  
  $parsed_file = TPL_C_DIR.md5($tpl_file).'.php';
  if(!file_exists($parsed_file) || filemtime($parsed_file) < filemtime($template_file)) {
   require_once './stupid_parser.class.php';
   $this->_parser = new StupidParser();
   $this->_parser->compile($tpl_file);
  }
  include $parsed_file;
}

这个方法是根据!file_exists($parsed_file)||filemtime($parsed_file)< filemtime($template_file)这条语句来判断是否编译过和模板文件是否更新过, 没有编译过和更新过模板文件都要重新编译.我们就要引入stupid_parser.class.php,并创建StupidParser对象,对模板文件进行编译.编译完,我们就引入编译之后的文件.这个编译之后的模板文件就是一个普通的PHP文件.

debug()方法
Debugg()方法就比较简单,就是引入stupid_debugger.class.php文件,创建StupidDebuger对象,调用StupidDebuger的start方法进行调试.

代码如下>>>

public function debug ($tpl_file) {
        if (include_once("stupid_debugger.class.php")) {
                $this->_debugger = new StupidDebugger($tpl_file);
                $this->_debugger->start();
        } else {
                exit( '错误:Debuger类文件不存在');
        }
}

至此,我们的Stupid类就写完了!下次我要介绍StupidParser类的编写.请继续支持.大家有什么意见或者建议可以提出!

show show全相:
[php]
<?php
define('TPL_DIR', './templates/');
define('TPL_C_DIR', './templates_c/');
class Stupid {
private $_tpl_vars;
private $_tpl_file;
private $_parser;
private $_debug;

public function Stupid() {
  if(!is_dir(TPL_DIR) || !is_dir(TPL_C_DIR)) {
   exit('错误:请正确设置模板文件夹和编译文件夹');
  }
}

public function assign($var, $value) {
  if(isset($var) && trim($var) != '') {
   $this->_tpl_vars[$var] = $value;
   return true;
  } else {
   exit('错误:请设置变量名');
  }
}

public function display($tpl_file) {
  $template_file = TPL_DIR.$tpl_file;
  if(!file_exists($template_file)) {
   exit('错误:模板文件不存在');
  }
  
  $parsed_file = TPL_C_DIR.md5($tpl_file).'.php';
  if(!file_exists($parsed_file) || filemtime($parsed_file) < filemtime($template_file)) {
   require_once './stupid_parser.class.php';
   $this->_parser = new StupidParser();
   $this->_parser->compile($tpl_file);
  }
  include $parsed_file;
}

function debug($tpl_file) {
  if (include_once("stupid_debugger.class.php")) {
   $this->_debugger = new StupidDebugger($tpl_file);
   $this->_debugger->start();
  } else {
   exit( '错误:Debuger类文件不存在');
  }
}
}
?>
[/php]

昵称: liexusong  时间: 2008-11-30 16:37:00
跟毛毛虫学写一个属于自己的淫荡的模板引擎
昵称: liexusong  时间: 2008-11-30 16:38:00
关注中..............
昵称: TankMe  时间: 2008-11-30 16:48:00
关注中..............
昵称: qxhy123  时间: 2008-11-30 16:55:00
多余的人路过,话说MVC做好的话,视图HTML PHP 分离实在是没多大意义
昵称: wclssdn  时间: 2008-12-08 17:49:00
期待中·············
昵称: 1oki  时间: 2008-12-08 17:50:00
期待...............
昵称: keailyf  时间: 2008-12-08 17:58:00
广告位出租
昵称: 张晨辉  时间: 2008-12-08 18:11:00
昵称: wzj5  时间: 2008-12-08 18:14:00
非常期待。。。
昵称: zfphp  时间: 2008-12-08 18:21:00
很快推出!大约这个星期之内会发布完成!请注意!
昵称: 只喝可乐的猫  时间: 2008-12-08 18:38:00
一直都想写个自己的模板,期待你的详细介绍。。。。。。。。
昵称: akas628  时间: 2008-12-08 18:42:00
期待...............
昵称: liexusong  时间: 2008-12-08 18:43:00
期待LZ的大作

占位学习
昵称: fly1983  时间: 2008-12-08 19:09:00
编译那个咱咋编译呢 ?正则?
昵称: ★xxXxx★  时间: 2008-12-09 13:56:00
好  不错不错  得学习学习
昵称: shanji  时间: 2008-12-09 14:25:00
期待LZ,过了一周了!
昵称: volew  时间: 2008-12-09 16:29:00
跟毛毛虫学写一个属于自己的淫荡的模板引擎
昵称: dinenghou  时间: 2008-12-09 16:40:00
更新了,请大家支持!!
昵称: Deman  时间: 2008-12-09 16:51:00
不知道是否可以申精呢???
昵称: 小鱼哥哥  时间: 2008-12-09 17:16:00
没有人支持!失望中................
昵称: liexusong  时间: 2008-12-10 09:57:00
毛毛 你准备怎么编译这个文件捏~
昵称: liexusong  时间: 2008-12-10 10:10:00
厉害,我还是先学smarty吧
昵称: liexusong  时间: 2008-12-10 13:43:00
菜鸟来学习
昵称: volew  时间: 2008-12-10 13:47:00
dingdingding
昵称: sinopf  时间: 2008-12-10 15:16:00
收藏
昵称: frode  时间: 2008-12-10 15:32:00
顶一个。。。争取早日整一个自己的framework出来。。。。
昵称: COOKIETEST  时间: 2008-12-15 22:42:00
快更新快更新
昵称: lanye  时间: 2008-12-15 22:44:00
没下文了?
昵称: kakashilw  时间: 2008-12-16 10:11:00
写的很不错的呀
昵称: COOKIETEST  时间: 2008-12-16 14:41:00
很牛很强大...
昵称: jackygz  时间: 2008-12-22 14:04:00
期待更新!
昵称: liangpz521  时间: 2008-12-22 14:31:00
kuai gengxina
昵称: csyrpeng  时间: 2008-12-22 14:43:00
速度更新
昵称: dirac  时间: 2008-12-22 17:21:00
这个星期之内会更新!谢谢支持!
昵称: COOKIETEST  时间: 2008-12-22 22:25:00
好东西~~ 正好有个问题
昵称: COOKIETEST  时间: 2008-12-22 22:25:00
最好也加个fetch方法,把display方法和fetch方法分开
昵称: liexusong  时间: 2008-12-22 22:28:00
关注中..............
昵称: wolf432  时间: 2008-12-22 22:47:00
更新完毕!谢谢大家支持!
昵称: COOKIETEST  时间: 2008-12-23 09:51:00
没人支持??失望ing......
昵称: delinking  时间: 2008-12-23 15:09:00
昵称: liexusong  时间: 2008-12-24 11:29:00
下载看看
昵称: liexusong  时间: 2008-12-24 13:47:00
好好研究  呵呵
昵称: phpzxh  时间: 2008-12-24 14:23:00
多谢支持!还有以后我会写个关于smarty内核的教程!!方便大家学习smarty
昵称: 阿米  时间: 2008-12-24 14:31:00
顶,学习ing
昵称: okjoyel  时间: 2008-12-24 14:36:00
问一个弱弱的问题,为什么要两个斜杠才能匹配美元符号,一个斜杠不能匹配吗?
\\$和\$的区别是什么啊
昵称: liexusong  时间: 2008-12-24 14:40:00
不能一个反斜杠的,因为第一个是用来转义PHP中的$,就是把$转成普通的字符,然后第二个反斜杠是用来正则表达式用的!!
昵称: sinan62  时间: 2008-12-24 16:19:00
原帖由 liexusong 于 2008-12-25 15:56 发表
不能一个反斜杠的,因为第一个是用来转义PHP中的$,就是把$转成普通的字符,然后第二个反斜杠是用来正则表达式用的!!
恍然大悟!
昵称: tetang1230  时间: 2008-12-25 15:24:00
咋个调用呢?
昵称: liexusong  时间: 2008-12-25 15:56:00
原帖由 huangqyun 于 2008-12-27 00:12 发表
咋个调用呢?
哦!原来有点错误!对不起!!现在改过了!调用:

require_once 'stupid.class.php';
$s = new Stupid();
$s->debug('index.tpl');


模版

<html>
<head></head>
<body>
<h2>我的模板引擎</h2>
<p>My name is : {$myname}</p>
{$array->foreach(key,value)}
  No:{@value}<br/>
{/foreach}
{if $myname == 'Tony'} Yes , My name is Tony {/if}
{#}echo hello world{#}
{include ""}
</body>
</html>


昵称: dirac  时间: 2008-12-26 01:12:00
发现个新问题,你用的<?php if ():   endif> 这是啥版本用到的语句,好像很早了吧。。。。
昵称: huangqyun  时间: 2008-12-27 00:12:00
没错!是很早,不过到现在也支持这种用法的!
昵称: liexusong  时间: 2008-12-27 00:53:00
难怪,记得从php3.0就开始有这种写法,现在都不流行了....哈,楼主也该适应一下时代潮流...
昵称: huangqyun  时间: 2008-12-27 00:59:00
哈哈!不是潮流的问题~那种写法比较有层次感!
昵称: liexusong  时间: 2008-12-27 01:04:00
即然还在,在问个问题,我看你在stupid_parser.class.php 文件中有个 $this->_tpl_vars['$1'] 的写法,我想问一下其中的'$1'是啥意思。
昵称: huangqyun  时间: 2008-12-27 01:05:00
不错的说
昵称: liexusong  时间: 2008-12-27 01:33:00
老大,求解呀,,在不!!!!!!!!!!!!!
昵称: huangqyun  时间: 2008-12-27 01:43:00
原帖由 huangqyun 于 2008-12-27 01:43 发表
即然还在,在问个问题,我看你在stupid_parser.class.php 文件中有个 $this->_tpl_vars['$1'] 的写法,我想问一下其中的'$1'是啥意思。
就是第一个括号匹配的东西~
昵称: xudongding  时间: 2008-12-27 15:54:00
支持楼主,要是代码里的注释写标准一点就更好了。
昵称: huangqyun  时间: 2008-12-27 17:14:00
哈哈,我顶你个肺啊,顶顶顶,等了很久了
昵称: liexusong  时间: 2008-12-27 18:58:00
多顶记下
昵称: phpzxh  时间: 2008-12-28 01:25:00
路过,不错!
昵称: COOKIETEST  时间: 2008-12-28 17:54:00
mark
昵称: COOKIETEST  时间: 2008-12-28 17:54:00
MVC这个不单单是在模板上吧
我希望能够继续说说MVC调用数据库 方面的内容。
昵称: davidachou  时间: 2008-12-28 18:31:00
谢谢,学习了
昵称: go_tit  时间: 2008-12-28 20:10:00
受益匪浅。。。。
感谢ing...
昵称: 李惟  时间: 2008-12-29 18:46:00
看不懂
昵称: cqc1008  时间: 2008-12-31 11:25:00
mark一下
昵称: libingcun  时间: 2009-01-02 16:25:00
多好的帖子啊
收藏!
昵称: apgbb  时间: 2009-01-04 11:20:00
顶。。。。。。。。。。。。。。。。。。。。
昵称: netbuddy  时间: 2009-01-07 00:46:00
[php]1.匹配变量的模式:{$var_name}2.匹配条件的模式:{if condition}.....................{/if}3.匹配注释的模式:{#}.......................................{#}4.匹配包含文件的模式:{include "file_name"}5.匹配foreach的模式(循环数组):{$array_name->foreach(key, value)}....................{/foreach}6.foreach中的变量表示:{@key} {@value}[/php]
这些能给写个使用的样例吗?我是新手,还不知道如何下手呢。
昵称: konakona  时间: 2009-01-07 01:27:00
楼主很好很强大!太牛了,服了你了!
昵称: lxydyx  时间: 2009-01-07 09:40:00
留个记号,有空来琢磨下
昵称: phpstar  时间: 2009-01-28 19:40:00
靠,收藏了再说吧。收藏了当私货用
昵称: lsx220  时间: 2009-01-29 16:30:00
好文,要学习!
昵称: 古嗣小井  时间: 2009-01-30 09:41:00
很好
昵称: 书君  时间: 2009-01-31 02:22:00
学习
昵称: kingboer  时间: 2009-02-01 15:41:00
需要分页的时候怎么弄呢
昵称: E蜗牛  时间: 2009-02-01 15:48:00
学习了,虽然不是很懂:
昵称: ginux  时间: 2009-02-06 04:28:00
等着你呢。
昵称: strongability  时间: 2009-02-15 16:08:00
private function _parse_include() {
        if(preg_match("/\{\s*include \"([^}]*)\"\s*\}/", $this->template, $file)) {
                if(trim($file[1]) == '') exit('错误:必须指定包含的文件');
                if(!file_exists(trim($file[1]))) exit('错误:文件不存在');


这个只检查一个的include文件是否存在.
昵称: situlh  时间: 2009-02-17 15:43:00
2个foreach要怎么办哦?

{$arr->foreach(k, v)}
        {$v->foreach(key, value)}
                {@key}- {@value}
        {/foreach}
{/foreach}
昵称: wanchun0222  时间: 2009-02-17 17:28:00
说真的,我只是介绍思想,而真正的实现要靠自己去努力了!!有不明白的可以与我讨论的,我很欢迎的!
昵称: appz  时间: 2009-02-24 22:09:00
谢谢毛毛虫
昵称: appz  时间: 2009-02-24 23:08:00
昵称: liexusong  时间: 2009-02-24 23:18:00
做个记号。以后研究
昵称: 站长刘  时间: 2009-02-25 11:28:00
学习学习
昵称: liuxingyuyuni  时间: 2009-02-25 11:34:00
学习了。。。。。。。。
昵称: xu569874  时间: 2009-02-25 14:59:00
先收藏~~回来学习学习~·
昵称: bingbin1321  时间: 2009-02-25 18:12:00
楼主真强,学习了
昵称: passter521  时间: 2009-03-05 20:42:00
收藏
昵称: piaomiao163  时间: 2009-03-05 21:50:00
楼主厉害。
讲得很清楚。
昵称: wxqaz  时间: 2009-03-11 20:34:00
不错好文章啊
昵称: highjade  时间: 2009-04-06 22:16:00
毛毛虫太強了
昵称: PHPShinelake  时间: 2009-04-22 15:59:00
好厉害啊,学习了
昵称: dlcs286  时间: 2009-05-13 16:10:00
学习了......
昵称: cvxcv  时间: 2009-05-13 17:04:00
lz写法好规范,真强~
昵称: slg1984  时间: 2009-05-13 20:50:00
Thanks, 一直在找相关的东西。就是在编译那块过不去。
昵称: luyinhu  时间: 2009-05-16 13:16:00
学习学习!!很受用
昵称: FreeLiver  时间: 2009-05-16 14:02:00
做个标记
昵称: fybird  时间: 2009-05-16 14:55:00
多余的人路过,话说MVC做好的话,视图HTML PHP 分离实在是没多大意义
昵称: blackgood  时间: 2009-05-16 14:55:00


高手啊!你写的差不多我都能看懂,可是要我自己写,就写不出来。

这个就是菜鸟和高手之间的区别吧
昵称: 哈出出  时间: 2009-05-18 16:19:00
跟毛毛学习
昵称: qq88316793  时间: 2009-05-18 18:46:00
先收着...慢慢欣赏..
昵称: mqh21364  时间: 2009-05-19 14:47:00
学习中^^^
昵称: abc20053608  时间: 2009-06-17 18:31:00
谢了。
昵称: chengwu555  时间: 2009-06-18 11:16:00
这些好东西,我怎么最近才发现呢?谢谢
昵称: lc0633  时间: 2009-06-22 13:14:00
学学。
昵称: qianzhengwei  时间: 2009-06-27 10:15:00
额....
我写的模板类不用正则,使用substr
嘿嘿,等把面向过程学好再学OOP
昵称: daimadaquan  时间: 2009-06-27 13:28:00
跟毛毛虫虫学写一个属于自己的模板引擎
TankMe 发表于 2008-11-30 16:48
昵称: yzhxiang  时间: 2009-06-27 19:44:00
占位学习中...
昵称: kilobug  时间: 2009-06-28 21:08:00
好厉害啊
昵称: 寒心  时间: 2009-07-22 17:23:00
即然有smrty干嘛要在换新的呢~ 成熟吗~
好用吗` 优化呢`
模板引擎说白了就是正则
昵称: googlere  时间: 2009-07-27 10:13:00
模板引擎说白了就是正则
昵称: linjize123  时间: 2009-07-27 20:52:00
呵呵,今天才看到,感觉不错,自己一直在用DISCUZ上抠下来的。
昵称: fly_yang  时间: 2009-07-27 21:13:00
感觉不错
昵称: wdvill  时间: 2009-08-10 20:17:00
..这个一定要学哈 。。。
昵称: shinian315  时间: 2009-10-23 14:12:00
我现在还学模板分离的,只是有概念而已,完全是 .Net 的三层概念,估计差不是很多。
昵称: wade2006  时间: 2009-10-24 12:01:00
让我 一次看个够0-0
昵称: bing19880122  时间: 2009-10-24 23:03:00
可惜我不能加分
昵称: 云端o枫o0  时间: 2009-10-26 14:43:00
不错不错,支持下
昵称: cocoglp  时间: 2009-10-30 15:36:00
额。。路过看一下~
昵称: 落寞三少  时间: 2009-11-23 10:35:00
谢谢LZ的分享
昵称: poptang  时间: 2009-11-23 13:13:00
学习,哈哈
昵称: zhoushj  时间: 2009-11-23 18:44:00
留个脚印 以后有时间再来看看
LZ辛苦了
昵称: ainiaa  时间: 2009-11-24 14:23:00
留个记号,有空来琢磨下
跟着楼猪思想走
昵称: 121928917  时间: 2009-12-02 11:13:00
关注中
昵称: ainiaa  时间: 2009-12-04 13:07:00
有疏漏哦,条件中写的变量无法编译。
如if($title){},assgin过来的title,无法在if语句的括号中编译出来
昵称: q60605  时间: 2009-12-08 10:11:00
记下了。等有时间试验下
昵称: alice147  时间: 2009-12-14 18:59:00
杭州www.fpzhuhai.com,青岛www.goodk123.info,佛山www.haofapiao.com,南通www.haokk111.info,珠海www.haokk123.info,哈尔滨www.kp1111.info,常州www.kp1234.info,重庆www.powerkp.info,东莞www.star1111.info,宁波www.star1234.info,深圳www.starkp.com,天津www.superkp111.com,南京www.superkp123.com,深圳www.szhaoexport.com,泉州www.topkp111.com,
昵称: blogtg123  时间: 2013-03-30 01:23:41