现在离职在家,突然发现没什么事儿做了,就研究研究了smarty,写了一个简单的搜索引擎。包含
assign赋值,display模版解析的方法,
新建一个MyTpl.class.php(其他名称也可以)
代码如下:
<?php
class MyTpl{
//初始化函数
function __construct($template_dir='templates/',$compile_dir='templates_c'){
$this->template_dir=rtrim($template_dir,'/').'/';
$this->compile_dir=rtrim($compile_dir,'/').'/';
$this->tpl_vars=array();
}
//赋值函数
function assign($tpl_var,$value=null){
if ($tpl_var!='') $this->tpl_vars[$tpl_var]=$value;
}
//模版解析
function display($fileName){
$tplFile=$this->template_dir.$fileName;
if (!file_exists($tplFile)) return false;
$comFileName=$this->compile_dir.'com_'.basename($tplFile).'.php';
if (!file_exists($comFileName)||filemtime($comFileName)<filemtime($tplFile)){
$repContent=$this->tpl_replace(file_get_contents($tplFile));
$handle=fopen($comFileName, 'w+');
fwrite($handle, $repContent);
fclose($handle);
}
require_once $comFileName;
}
//模版替换函数
private function tpl_replace($content){
$pattern=array(
'/<\{\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-xff]*)\s*\}>/i', //解析变量
'/<\{\s*if\s*(.+?)\s*\}>(.+?)<\{\s*\/if\s*\}>/ies', //if标签解析
'/<\{\s*else\s*if\s*(.+?)\s*\}>/', //elseif解析
'/<\{\s*else\s*\}>/', //else解析
'/<\{\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*\}>(.+?)<\{\\s*\/loop\s*}>/is', //匹配loop标签
'/<\{\s*loop\s+\$(\S+)\s+\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*=>\s*\$(\S+)\s*\}>(.+?)<\{\s*\/loop\s*\}>/is>/',//遍历loop中的键和值
'/<\{\s*include\s+[\"\']?(.+?)[\"\']?\s*\}>/ie', //匹配include
);
//替换成php
$replacement=array(
'<?php echo $this->tpl_vars["${1}"]?>', //变量替换
'$this->stripvtags(\'<?php if(${1}){?>\',\'${2}<?php}?>\')',
'$this->stripvtags(\'<?php } elseif(${1}) { ?>\',"")',
'<?php } else { ?>',
'<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"]) { ?>${3}<?php } ?>',
'<?php foreach($this->tpl_vars["${1}"] as $this->tpl_vars["${2}"]=>$this->tpl_vars["${3}"]){?>$(4)<?php } ?>',
'file_get_contents($this->template_dir."${1}")'
);
$repContent=preg_replace($pattern, $replacement, $content);
if (preg_match('/<\{([^(\}>)]{1,})\}>/', $repContent)){
$repContent=$this->tpl_replace($repContent);
}
return $repContent;
}
//替换条件语句中对应的值
private function stripvtags($expr,$statement){
$var_pattern='/\s*\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*/is';
$expr=preg_replace($var_pattern, '$this->tpl_vars["${1}"]', $expr);
$expr=str_replace("\\\"", "\"", $expr);
$statement=str_replace("\\\"", "\"", $statement);
return $expr.$statement;
}
}
以上很简单,就是赋值,然后做模版解析以后再输出,最复杂的一部分就是正则替换这一部分,写了很久,有时间还是借鉴一下smarty的吧。
接下来就测试一下,新建一个inde.php
require_once 'plugins/MyTpl.class.php';
$Tpl=new MyTpl();
$title='第一个标题';
$Tpl->assign('title',$title);
$Tpl->display('index.tpl');
并且新建templates目录,templates_c目录其他根据实际情况来写,然后在templates中新建一个index.tpl,写上相应的代码,我只是做一个简单的测试,
<html>
<head><title><{$title}></title></head>
<body>
<{$title}>
</body>
</html>
然后在浏览器中预览,就可以实现,我写的正则替换里,也包括一个loop的foreach替换标签。大家可以继续扩展完善,我也会继续完善一套自己的模版引擎。