自行开发的 轻量级 模板引擎

模板的作用:表现与实现相分离.

项目中考虑 Smarty或其它模板引擎,过于庞大,功能较多,但项目中使用的较少. 

另外,模板语法过于复杂,增加了开发人员的学习成本.

故,自行开发了一个小模板引擎,实现了编译及缓存功能.

代码如下:

<?php
/**
 * 模板类
    一.for循环
        <for($i=0;$i<count($arr);$i++)>              
        <endfor>
        缺陷:如表达式中有>(大于号),将导致视图在DW中出现多余字符
    二.foreach循环
        <foreach($arr as $k=>$v)>                   
        <endforeach>
        缺陷:'=>' 将导致视图在DW中出现多余字符
    三.if判断
        <if($i>5)>
        <elseif($i>2)>
        <else>
        <endif>
        缺陷:如果表达式中有>(大于号),将导致视图在DW中出现多余字符
    四.嵌套原生代码
        <php>
        </php>
    五.子模板包含
        <include('子模板',参数数组)>
        注意:紧密连接
    六.自我感知
        <model(结果变量名 模型类名 方法(参数表))>
        注意:这个与PHP语法实在无法一致了,中间是空格分开的,此句等同于 <?php $结果变量名=模型类名::instance()->方法(参数表) ?>
    七.显示函数返回值
        {date('Y-m-d H;i:s')}
        注意:既然是函数调用,最后就应该是')'结束
    八.显示变量的值
        {$变量}
        {$对象.属性}
        {$数组[下标]}
    九.赋值
        <assign($变量=表达式)>

    全局注意:
        '<for(',')>' 以及 '<endfor>' 必须紧密连接
        '<foreach(',')>'以及'<endforeach>' 必须紧密连接
        其它标签也是如此
 */
class STemplate{
   
    /**
     * 显示视图,如果需要,智能编译
     *
     * @param string $view 视图
     * @param array $params 参数
     */
    static public function display($view,$params){
        extract($params);
        include(self::getTpl($view));
    }
   
    /**
     * 根据视图获取编译后的模板文件,会自动进行智能编译
     *
     * @param string $view 视图
     * @return string 模板文件(带路径)
     */
    static private function getTpl($view){
        $source=SConfig::system('dir_view').$view.'.'.SConfig::system('suffix_view');
        $target=SConfig::system('dir_template').$view.'.'.SConfig::system('suffix_template');
        if(!file_exists($source)){
            throw new Exception('View file not exist:'.$view);
        }
       
        //调试模式 或 缓存文件不存在 或 缓存文件过期 则:重新编译
        if(!file_exists($target) or filemtime($source)>filemtime($target)){
            $dirs=explode('/',$view);
            $path=SConfig::system('dir_template');
            for($i=0;$i<count($dirs)-1;$i++){
                $path.=$dirs[$i];
                if(!is_dir($path)){
                    mkdir($path);
                }
                $path.=DIRECTORY_SEPARATOR;
            }
            $content=self::complie($view,file_get_contents($source));
            file_put_contents($target,$content);           
        }
        return $target;
    }
   
    /**
     * 预编译模板
     *
     * @param string $view        模板名称
     * @param string $source    原模板内容
     * @return string            编译后结果
     */
    static private function complie($view,$source){
        //不允许出现PHP代码
        if (strpos($source,'<?')!==false){
            throw new Exception('Cant\'t user php code in template:'.$view);
        }
       
        //替换
        $target=preg_replace(
            array(
                '/<for\b(\(.*\))>/',                            //匹配 for 循环开始,与PHP语法一致
                '/<endfor>/',                                    //匹配 for 循环结束
                '/<foreach\b(\(.*\))>/',                        //匹配 foreach 循环开始,与PHP语法一致
                '/<endforeach>/',                                //匹配 foreach 循环结束
                '/<if\b(\(.*\))>/',                                //匹配 if 开始,与PHP语法一致
                '/<elseif\b(\(.*\))>/',                            //匹配 elseif,与PHP语法一致
                '/<else>/',                                        //匹配 else
                '/<endif>/',                                    //匹配 if 结束
                '/<php>/',                                        //匹配 原生代码开始
                '/<\/php>/',                                    //匹配 原生代码结束
                '/<include\b(\(.*\))>/',                        //匹配 子模板包含,语法 <include('子模板',参数数组)>
                '/<model\b\(([\w\d]+)\s([\w\d]+)\s(.*)\)>/',    //匹配 自我感知,语法 <model(数据 模型名称 方法(参数))>
                '/{(.*\))}/',                                    //匹配 显示函数返回值,与PHP语法一致
                '/{\$([^}]*)}/',                                //匹配 显示变量的值,与PHP语法一致
                '/<assign\b\((.*)\)>/',                            //匹配 赋值 <assign($var=exp)>
            ),
            array(
                '<?for\1:?>',                                    //替换 For 循环开始
                '<?endfor?>',                                    //替换 For 循环结束
                '<?foreach\1:?>',                                //替换 Foreach 循环开始
                '<?endforeach?>',                                //替换 Foreach 循环结束
                '<?if\1:?>',                                    //替换 If 开始
                '<?elseif\1:?>',                                //替换 Elseif
                '<?else:?>',                                    //替换 Else
                '<?endif?>',                                    //替换 If 结束
                '<?',                                            //替换 原生代码开始
                '?>',                                            //替换 原生代码结束
                '<?display\1?>',                                //替换 子模板包含
                '<?$\1=\2::instance()->\3?>',                    //替换 自我感知
                '<?=\1?>',                                        //替换 显示函数返回值的开始
                '<?=$\1?>',                                        //替换 显示变量的值   
                '<?\1?>',                                        //替换 赋值
            ),$source);
           
            //如果不是调试模式,则去除首尾空格
            if(!SDebug::isDebug()){
                $target=preg_replace('/^\s*|\s*$/m','',$target);
            }
        return $target;
    }
}



注:大家使用时,要将其中的部分代码进行修改.  将路径,后缀修改为自己项目中的实际路径与后缀,同时调试代码去除.

<script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/buttonLite.js#style=-1&uuid=&pophcol=3&lang=zh"></script> <script type=text/javascript charset=utf-8 src="http://static.bshare.cn/b/bshareC0.js"></script>
阅读(163) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值