袁来如此的工作笔记
袁来如此的工作笔记
竹杖芒鞋轻胜马,谁怕? 一蓑烟雨任平生。

PHP 实现简单的模板引擎

浏览量:634

模板引擎作为视图层和模型曾分离的一种解决方案。

首先我们新建一个Template.class.php 的文件

class Template{
        private $arrayConfig = array(
        'suffix'      => '.m',           //设置模板文件
        'templateDir' => 'template/',     //设置模板所在的文件夹
        'compileDir'  => 'cache',
        'debug'      => false,        //设置编译后存放的目录
        'cache_htm'   =>  true,      //是否需要编译成静态的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(); //调试信息
    public function __construct($arrayConfig =array()){
            //返回当前UNIX时间戳和微妙数
        $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){
         
        //设置timeflag (判断当前时间-模板文件上次修改的时间)是否小于设置的缓存时间
        //如果小于则返回TRUE
         
            $timeFlag = (time()-@filemtime($cacheFile))<$this->arrayConfig['cache_time']?
            true:false;
    //1,判断缓存文件是否存在,
    //2,缓存文件是否有内容
    //3,时间是否在设置的缓存时间之内      
            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('找不到相对应的模板');
        }
        $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();
            }
            //函数从数组中把变量导入到当前的符号表中
            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{
        //如果缓存文件时间小于设定的时间
        //直接读取缓存文件
            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 调试函数
    **/
    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 "模板包含标签数目",$this->debug['count']."</br>";
            echo "是否使用静态缓存",$this->debug['cached']."</br>";
            //echo "模板引擎实例参数",var_dump($this->getConfig());
        }
    }
    /******
        清楚缓存的文件
     
     
    *****/
    public function clean($path = null){
        if($path = null){
            $path = $this->arrayConfig['CompileDir'];
            $path = glob($path.'*'.$this->arrayConfig['suffix_cache']);
            //glob 函数返回匹配指定的文件夹目录
             
        }else{
            $path = $this->arrayConfig['compileDir'].md5($path).'.htm';
            foreach((array)$path as $v){
            //删除
                unlink($v);
            }
        }
    }
     
     
     
}


新建一个 Compile.class.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

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>


显示截图

101426_h02D_2380832.png

打赏