继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

PHP中面向对象中的模板引擎类

牧羊人nacy
关注TA
已关注
手记 52
粉丝 5
获赞 25

<?php

 

/**

* 模版引擎类

*/

class Tpl

{

 

    //缓存目录

    protected $cacheDir = './Cache/';

    //模版目录

    protected $tplDir = './Tpl/';

    //保存变量的成员方法

    protected $vars = [];

    //缓存有效期

    protected $cacheLifeTime = 3600;

 

 

    //初始化成员属性

    public function __construct($tplDir = null ,$cacheDir = null ,$cacheLifeTime = null)

    {

        //判断缓存目录是否存在

        if (isset($tplDir)) {

            if ($this->_checkDir($tplDir)) {

                $this->tplDir = rtrim($tplDir,'/') . '/';

            }

        }

        //判断模板路径是否存在  如果不存在要创建,权限是否可写 就需要更改权限

        if (isset($cacheDir)) {

            if ($this->_checkDir($cacheDir)) {

                $this->tplDir = rtrim($cacheDir,'/') . '/';

            }

        }

        //初始化缓存时间

        if (isset($cacheLifeTime)) {

            $thsi->cacheLifeTime = $cacheLifeTime;

        }

    }

 

    //目录的创建以及权限的处理

    private function _checkDir($path)

    {

        //判断是否存在目录以及是否是目录

        if (!file_exists($path) || !is_dir($path)) {

             return mkdir($path,0755,true);

        }

 

        //判断目录的权限是否可读可写

        if (!is_readable($path) || !is_writable($path)) {

            return chmod($path,0755);

        }

 

        return true;

    }

 

    //分配变量 主要的目的是将模板中需要处理的代码在php中替换做准备

    public function assign($key,$val)

    {

        $this->vars[$key] = $val;

 

    }

 

    //display 显示模板文件

    public function display($file,$isExecute = true ,$uri = null)

    {

 

         //获得模板路径(模板目录路径+模板文件)

         $tplFilePath = $this->tplDir.$file;

        //判断文件是否存在

        if (!file_exists($tplFilePath)) {

            exit('模板文件不存在');        }

        //获得编译文件路径(组合一个全新的文件名和路径)

        $cacheFile = md5($file.$uri) . '.php';

 

        $cacheFilePath  = $this->cacheDir . $cacheFile;

 

        //检测是否编译过 是否修改过模板文件 如果变编译过 而且在有效期内则不编译

        if (!file_exists($cacheFilePath)) {

            $html = $this->compile($tplFilePath);

 

        } else {

 

            //如果修改过模版文件  就需要删除原来的编译文件重新编译

            if (filemtime($tplFilePath) > filemtime($cacheFilePath)) {

 

                //删除原来的文件

                unlink($cacheFilePath);

 

                //重新编译

                $html = $this->compile($tplFilePath);

 

            }

 

            //文件创建时间+缓存有效期 > time() [当前时间], 没有过期  否则过期

            $isTimeout = (filemtime($tplFilePath) + $this->cacheLifeTime > time()) ? false : true;

 

            if ($isTimeout) {

                $html = $this->compile($tplFilePath);

            }

        }

 

        //编译

        if (isset($html)) {

            if (!file_put_contents($cacheFilePath, $html)) {

                exit('编译文件写入失败');

            }

        }

 

        //执行

        if ($isExecute) {

            extract($this->vars);

            include $cacheFilePath;

        }

    }

 

    //编译的方法  将html的php代码替换成php代码来执行 并且生成一个缓存

    protected function compile($tplFilePath)

    {

        //将整个文件读入一个字符串

        $html = file_get_contents($tplFilePath);

 

        //正则替换规则

        $keys = [

            '{if %%}' => '<?php if(\1): ?>',

            '{else}' => '<?php else : ?>',

            '{else if %%}' => '<?php elseif(\1) : ?>',

            '{elseif %%}' => '<?php elseif(\1) : ?>',

            '{/if}' => '<?php endif;?>',

            '{$%%}' => '<?=$\1;?>',

            '{foreach %%}' => '<?php foreach(\1) :?>',

            '{/foreach}' => '<?php endforeach;?>',

            '{for %%}' => '<?php for(\1):?>',

            '{/for}' => '<?php endfor;?>',

            '{while %%}' => '<?php while(\1):?>',

            '{/while}' => '<?php endwhile;?>',

            '{continue}' => '<?php continue;?>',

            '{break}' => '<?php break;?>',

            '{$%% = $%%}' => '<?php $\1 = $\2;?>',

            '{$%%++}' => '<?php $\1++;?>',

            '{$%%--}' => '<?php $\1--;?>',

            '{comment}' => '<?php /* ',

            '{/comment}' => ' */ ?>',

            '{/*}' => '<?php /* ',

            '{*/}' => '* ?>',

            '{section}' => '<?php ',

            '{/section}' => '?>',

            '{{%%(%%)}}' => '<?=\1(\2);?>',

 

            '{include %%}' => '<?php include "\1";?>',

 

        ];

 

            //通过遍历 然后一一替换

        foreach ($keys as $key => $value) {

                //正则匹配替换

            $patten = '#' . str_replace('%%', '(.+)', preg_quote($key,'#')) . '#imsU';

 

            $replace = $value;

 

            //包含文件处理 include处理方式不一样

            if (stripos($patten, 'include')) {

                // 执行一个正则表达式搜索并且使用一个回调进行替换

                $html = preg_replace_callback($patten, array($this,'parseInclude'), $html);

 

            } else {

 

                $html = preg_replace($patten, $replace, $html);

            }

 

        }

        return $html;

 

    }

 

    protected function parseInclude($data)

    {

 

        $file = str_replace(['\'','"'],'',$data[1]);

 

        $path = $this->parsePath($file);

 

        $this->display($file,false);

 

        return '<?php  include "' . $path . '";?>';

    }

 

    //处理文件名  将汉字符号等统一设置为32位的加密文件名

    protected function parsePath($file)

    {

 

        $path = $this->cacheDir . md5($file).'.php';

 

        return $path;

    }

 

    //删除缓存文件(递归)

    public function clearCache()

    {

        self::delDir($this->cacheDir);

    }

 

    //递归删除缓存的文件

    public static function delDir($path)

    {

        $res = opendir($path);

 

        while($file = readdir($res)){

            if ($file == '.' || $file == '..') {

                continue;

            }

 

            $newPath = $path.'/'.$file;

 

            if (is_dir($newPath)) {

 

                self::delDir($newpath);

            } else {

                unlink($newPath);

            }

        }

    }

 

}

测试代码:

1

2

3

4

5

6

$tpl new Tpl();

$tpl->assign('hello','world');

$tpl->assign('chensen','你好森林么么哒'); 



 $tpl->display('index.html');


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP