今天闲着没事,看到一篇php模板引擎的文章,感觉写的还是太烦琐了,并且语法也不够简单,于是萌生了自己打造一款超简单实用的模板引擎的念头。按照笔者的想法模板引擎应该具有的特点是:

  1. 语法简单,最好是php原生语法
  2. 执行速度快
  3. 支持缓存编译,这点很重要哦,可以节约很多模板解析时间~

思路有了,一切开始就绪,首先是设计模板引擎的语法,根据思路,语法设计如下(注意:所有模板语法占用一行):

#$var_name //变量输出,当时支持数组之类的啦

#if($cond=1){

.....html内容

#}

#foreach($arr as $v){

<li>

#$v

</li>

#}

下面给出代码:

<?php
  class template{
      public    $delim = "#";
      public    $template_path = "./template";
      public    $template_cache = "./cache";
      public    $cache_time = 86400;
      public    $template_surfix = ".html";
      private   $current_template = "";
      private   $cache_file = "";
      private   $data = array();

      public function __get($name){
       return isset($this->data[$name])?$this->data[$name]:false;
      }

      public function __set($name,$value){
          $this->data[$name] = $value;
      }

      public function assign($name,$value){
          $this->$name = $value;
      }

      public function display($template){
          $this->current_template = $template;
          if($this->chk_cache()){
            @extract($this->data);
            include ($this->cache_file);
          }
          else{
              $this->compile();
          }
      }

      private function token($str){
        $tok = strtok($str, $this->delim);
        while ($tok !== false) {
            $ret =  substr($tok,0,strpos($tok,"\n"));
            $tok = strtok($this->delim);
            $retarr[$ret] = token_get_all("");
        }
        return $retarr;
      }

      private function parse($str){
        $retarr =  $this->token($str);
        foreach($retarr as $key=>$v){
            $tokenname = @token_name($v[1][0]);
            switch($tokenname){
                case 'T_VARIABLE':
                   $str = str_replace("#".$key,"<?php echo {$v[1][1]} ?>",$str);
                   break;
                default:
                   $str = str_replace("#".$key,"<?php $key ?>",$str);
            }
        }
        return ($str);
      }

      private function compile(){
          $source = file_get_contents($this->template_path."/".$this->current_template.$this->template_surfix);
          $result = $this->parse($source);
          file_put_contents($this->cache_file,$result);
          @extract($this->data);
          include ($this->cache_file);
      }

      private function chk_cache(){
          $this->cache_file = $this->template_cache."/".md5($this->current_template).".php";
          if(file_exists($this->cache_file) && time()-filemtime($this->cache_file)<$this->cache_time){
            return true;
          }
          return false;
      }

  }
?>

测试代码:

<?php
    include "template.class.php";
    $t = new template();
    $t->assign('test','is a test value');
    $t->assign('tdshow',1);
    $t->display('index');
?>

模板:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
<head>
 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
 <title></title>
</head>
<body>

 #$test
    <table>
      #if($tdshow=='1'){
      <tr>
        <td>td is show</td>
      </tr>
      #}
    </table>
    <ul>#for($i=0;$i<10;$i++){
    <li>
    #$test
    </li>
    #}
    </ul>

</body>
</html>

需要改进的地方:

  1. 暂不支持子模板
  2. 语法必须当独一行,否则会出错
  3. 笔者会在后续版本中开发新功能,并力求简单实用,争取在100行代码内完成这些任务!

毕竟花的时间太短,只有1个小时吧^_^,对于一个成熟的代码来说,开发时间实在少的可怜,不过为大家提供一种新思路,个人觉得,没必要一提到php模板引擎就一定要用到正则表达式嘛~