代码解释类似smart模版引擎原理

416 查看

先贴下目录结构:

 ls
compiled/  index.php  source/  ss.class.PHP

compiled 模版编译后的目录
index.php
source 模版源文件夹
ss.clsss.php 山寨类smarty文件
ss.clsss.php
<?php
    class Template{

        private $templateDir;//源文件文件夹
        private $compileDir;//编译之后文件夹
        private $leftTag="{#";//需要替换的左边标记
        private $rightTag="#}";//需要替换的左边标记
        private $templateExtName=".html";
        private $currentTemp;//当前正在编译的模版文件名
        private $outputHtml;//正在读取的模版文件
        private $varPool=array();//模版变量池

        public function__construct($templateDir,$compileDir,$leftTag=null,$rightTag=null,$templateExtName=null){

            $this->templateDir=$templateDir;
            $this->compileDir=$compileDir;

            if(!empty($leftTag))$this->leftTag=$leftTag;
            if(!empty($rightTag))$this->rightTag=$rightTag;
            if(!empty($templateExtName))$this->templateExtName=$templateExtName;
        }

        // 把用到的变量放入到变量池子中
        public function assign($tag,$var){
            $this->varPool[$tag]=$var;
        }

        // 取出一条变量,用于下面的str_replace正则替换
        public function getVar($tag){
            return $this->varPool[$tag];
        }

        //获取模版源文件
        public function getSourceTemplate($templateName){

            $this->currentTemp=$templateName;

            // 拼接完整文件名
            $sourceFileName=$this->templateDir.$this->currentTemp.$this->templateExtName;
            $this->outputHtml=file_get_contents($sourceFileName);
        }

        // 编译
        public function compileTemplate($templateName=null){

            // 获取当前需要编译的模版
            $templateName=empty($templateName)?$this->currentTemp:$templateName;

            // $pattern='/\{#(\$[a-zA-Z_]\w+)#\}/';// 符合php变量命名

            //preg_quote 可对用户界定的左右定界符中出现. \ + * ? [ ^ ] $ ( ) { } = ! < > | : -进行转义
            $pattern="/".preg_quote($this->leftTag);

            //前后加上空格匹配任意次匹配类似<h1>{# $name  #}</h1>
            $pattern.=' *\$([a-zA-Z_]\w*) *';

            $pattern.=preg_quote($this->rightTag)."/";

             // $1写成\\1也可以 ,$1为正则的匹配单元,或者可以说是总(子)模式
            $this->outputHtml=preg_replace($pattern, '<?php echo $this->getVar(\'$1\');?>', $this->outputHtml);

            // 注意不要用双引号,会解析getvar Template::$getVar报notice错误
            $this->outputHtml=preg_replace($pattern, "<?php echo $this->getVar(\\1);?>", $this->outputHtml);

            $compileFileName=$this->compileDir.md5($templateName).$this->templateExtName;

            file_put_contents($compileFileName, $this->outputHtml);
        }

        // 输出
        public function display($templateName=null){

            $templateName=empty($templateName)?$this->currentTemp:$templateName;

            include($this->compileDir.md5($templateName).$this->templateExtName);

        }

    }

简单调用如下:(index.php中内容)

<?php
    include('ss.class.php');

    $basedir=str_replace('\\', '/', dirname(__FILE__));//兼容linux等区分大小写平台

    $test=new Template($basedir."/source/",$basedir."/compiled/");

    $test->assign('name','iamtb');

    $test->assign('pageTitle','tbtbt');

    $test->getSourceTemplate('index');

    $test->compileTemplate('index');

    $test->display('index');