比较phpcms的view模板分析就强多数了,接待高手帮小编校勘一下
分类:热门新闻

?php

CodeIgniter很适合小站点应用开发,但是它自带的view功能可能会给不懂PHP的前端人员带来麻烦。 相比之下phpcms的view模板解析就强大多了,所以这里就把PHPCMS的模板解析功能剥离出来,加到PHPCMS上。
首先在CodeIgniter libraries中 增加 template_cache.php
复制代码 代码如下:
/**
 *  模板解析缓存
 */
final class template_cache {

/**php简单 模板技术* 作者:牛哄哄* QQ:455703030* 声明:我正则写的不地道,欢迎高手帮我修改一下* 可自由传播、使用,但请保留此信息*/

    public $cache_path;
    public function __construct()
    {
        //$CI =& get_instance();
        $this->cache_path = APPPATH.'views';
    }

class FLEA_View_NHH{//模板存储目录public $viewDir = null;//缓存存储目录public $cacheDir = null;//是否过滤缓存中多余空格、Tab、回车public $filterCache = true;//模板中需要显示的数据private $data = array();public function __construct(){$viewConf = (array)FLEA::getAppInf('viewConfig');if (empty($viewConf)) {FLEA::loadClass('FLEA_Exception_ExpectedFile');__THROW(new FLEA_Exception_ExpectedFile('The config file is not found: '.$viewConf));}$this-viewDir = $viewConf['viewDir'];$this-cacheDir = $viewConf['cacheDir'];$this-filterCache = $viewConf['filterCache'];}public function assign($var, $value){$this-data[$var] = $value;}public function display($viewName){$view = $this-viewDir.'/'.$viewName.'.html';$cache = $this-cacheDir.'/'.$viewName.'.php';if (!file_exists($view)) {FLEA::loadClass('FLEA_Exception_ExpectedFile');__THROW(new FLEA_Exception_ExpectedFile('The view file is not found: '.$view));}if (filemtime($view) @filemtime($cache)) {$this-parseView($view, $cache);}if (file_exists($cache)) {if (!defined('IN_THIS_VIEW')) { define('IN_THIS_VIEW', TRUE); }include($cache);} else {FLEA::loadClass('FLEA_Exception_ExpectedFile');__THROW(new FLEA_Exception_ExpectedFile('The cache file has not read in correctly: '.$cache));}}private function parseView($view, $cache = null){/* 如果模板不存在,则输出错误消息 */if (!file_exists($view)) {FLEA::loadClass('FLEA_Exception_ExpectedFile');__THROW(new FLEA_Exception_ExpectedFile('The view file is not found: '.$view));}/* 读取模板内容为一个字符串 */$view = file_get_contents($view);/* 将!--{ }--替换为{{ }} */$view = str_replace(array('!--{', '}--'), array('{{', '}}'), $view);/* 清除注释 */$view = preg_replace(//{/{/*(.*?)/*/}/}/, '', $view);/* 解析assign方法引入的变量 */$view = preg_replace('//$([A-Za-z0-9_]+)/', '$this-data[/'//1/']', $view);/* 机械模板内部定义变量 */$view = preg_replace('//$/[([A-Za-z0-9_]+)/]/', '$//1', $view);/* 解析{{ $var }}基本变量输出标签 */$view = preg_replace('//{/{/s*/$(.+?)/s*/}/}/', '? echo $//1; ?', $view);/* 解析{{ include }}标签 */$view = preg_replace('//{/{/s*include/s+(.+?)/s*/}/}/', '? include //1; ?', $view);/* 解析{{ html }}标签 */$view = preg_replace('//{/{/s*html/s+(.+?)/s*/}/}/', '? echo file_get_contents(//1); ?', $view);/* 解析{{ code }}标签 */$view = preg_replace('//{/{/s*code/s+(.+?)/s*/}/}/', '? //1; ?', $view);/* 解析{{ if }}标签 */$view = preg_replace('//{/{/s*if/s+(.+?)/s*/}/}/', '? if (//1) { ?', $view);/* 解析{{ elseif }}标签 */$view = preg_replace('//{/{/s*elseif/s+(.+?)/s*/}/}/', '? } elseif(//1) { ?', $view);/* 解析{{ while }}标签 */$view = preg_replace('//{/{/s*while/s+(.+?)/s*/}/}/', '? while (//1) { ?', $view);/* 解析{{ foreach }}标签 */$view = preg_replace('//{/{/s*foreach/s+(.+?)/s*/}/}/', '? foreach (//1) { ?', $view);/* 解析{{ for }}标签 */$view = preg_replace('//{/{/s*for/s+(.+?)/s*/}/}/', '? for (//1) { ?', $view);/* 解析{{ else }}标签 */$view = preg_replace('//{/{/s*else/s*/}/}/', '? } else { ?', $view);/* 解析{{ /while }},{{ /if }},{{ /for }},{{ /foreach }}标签 */$view = preg_replace('#/{/{/s*/[a-z]+/s*/}/}#', '? } ?', $view);/* 递归解析嵌套的子模板 */if (preg_match_all('//{/{/s*view/s+(.+?)/s*/}/}/', $view, $viewsInView)) {/* 循环解析此模板中所有子模板,并将解析结果保存到数组$views */$viewInViews = array();foreach ($viewsInView[1] as $viewInView) {$viewInViews[] = $this-parseView(eval('return '.$viewInView.';'));}/* 将该模板中所有子模板的标签分别替换为其对应的解析结果 */$view = str_replace($viewsInView[0], $viewInViews, $view);}/* 合并相邻标签的解析结果 */$view = preg_replace('//?/s*/?/', '', $view);/* 如果开启了缓存过滤,则过滤掉其中多余空格、Tab、回车 */if ($this-filterCache == true) {$view = preg_replace('//s+/', ' ', $view);}/* 如果是在解析子模板,则返回解析结果 */if ($cache == null) { return $view; }/* 加入防止直接访问缓存的代码 */$view = '? if (!defined(IN_THIS_VIEW)) exit(The page is not found!); ?'.$view;/* 将模板解析结果写入缓存文件 */@file_put_contents($cache, $view);}}

    /**
     * 编译模板
     *
     * @param $module    模块名称
     * @param $template    模板文件名
     * @param $istag    是否为标签模板
     * @return unknown
     */

/*** 一、配置* 配置文件请在FLEA的配置文件中修改* 格式为:* 'viewConfig' = array(* 'viewDir' = '', //模板文件路径* 'cacheDir' = '', //缓存文件路径* 'filterCache' = true, //是否在模板解析完毕后对缓存进行优化* );* * 二、标签* 模板文件后缀名为.html* 标签同时支持两种!--{ }--或{{ }},你可以根据情况自由使用* 1、{{* *}} 添加注释,只支持单行,多行的不知道怎么写,郁闷* 2、{{ $abc }} 输出一个变量,变量的格式化输出请使用{code }标签执行一个函数进行格式化输出* 3、{{ $[abc] }} 输出一个模板内部定义的变量,变量名要用中括号括起来* 4、{{ include 'abc/bcd.php' }} 包含一个动态文件,这个文件中可使用通过assign方法加入的变量和模板内部定义的变量,但不可以使用本引擎支持的标签* 5、{{ html 'abc/bcd.html' }} 包含一个静态文件,此标签仅在PHP5下可用,被包含的文件中不可使用任何变量或标签,此标签可获得几倍于include标签的性能* 6、{{ code echo substr($abc,1) }} 执行一段PHP代码,包括赋值,函数等等* 7、{{ if $abc==1 }}和{{ elseif $abc==2 }}和{{ /if }} 判断,分支* 8、{{ while $abc1000 }}和{{ /while }} while循环* 9、{{ for $i=0;$i1000;$i++ }}和{{ /for }} for循环* 10、{{ foreach $abc as $k = $v }}和{{ /foreach }} foreach循环* 11、{{ view 'abc/bcd.html' }} 嵌套另一个模板,支持模板的无限嵌套* * 注意:* 1,include,html,view标签可使用常量来指定路径,这样会更加方便* 2,assign引入的变量与模板内部定义的变量采用不同的命名空间,因此可重名* 3,对于while,foreach,for循环需要引入的变量,最好采用模板内部定义的变量* 4,模板内部定义变量 {{ code $[i]=1 }}* 5,所有标签内部不可包含{}大括号,否则无法正确解析* 6,所有标签的参数部分必须写为单行,否则无法正确解析* 7,在调试时,为方便查看编译结果可关闭缓存优化,发布时,建议开启,可提高性能* 8,此模板引擎仅可于FLEA下使用,若需不依赖FLEA的版本,请自行修改* 9,标签中的参数使用PHP的语法* 10,数组的引用与输出{{ $abc['id'] }}* 11,所有标签一律小写* 12,标签的参数中不可包含{{或}},否则会解析错误*/

    public function template_compile($module, $template, $style = 'default') {

?

        $tplfile= APPPATH.'views'.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.$template.'.php';

        if (! file_exists ( $tplfile )) {
            show_error($tplfile ,  500 ,  'Template does not exist(1)');
        }

        $content = @file_get_contents ( $tplfile );

        $filepath = $this->cache_path.DIRECTORY_SEPARATOR.'caches_template'.DIRECTORY_SEPARATOR.$style.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR;

       
        if(!is_dir($filepath)) {
            mkdir($filepath, 0777, true);
        }
        $compiledtplfile = $filepath.$template.'.php';
        $content = $this->template_parse($content);
        $strlen = file_put_contents ( $compiledtplfile, $content );
        chmod ( $compiledtplfile, 0777 );
        return $strlen;
    }

    /**
     * 更新模板缓存
     *
     * @param $tplfile    模板原文件路径
     * @param $compiledtplfile    编译完成后,写入文件名
     * @return $strlen 长度
     */
    public function template_refresh($tplfile, $compiledtplfile) {
        $str = @file_get_contents ($tplfile);
        $str = $this->template_parse ($str);
        $strlen = file_put_contents ($compiledtplfile, $str );
        chmod ($compiledtplfile, 0777);
        return $strlen;
    }    

    /**
     * 解析模板
     *
     * @param $str    模板内容
     * @return ture
     */
    public function template_parse($str) {
        $str = preg_replace ( "/{templates+(.+)}/", "", $str );
        $str = preg_replace ( "/{includes+(.+)}/", "", $str );
        $str = preg_replace ( "/{views+(.+)}/", "load->view(\1); ?>", $str );
        $str = preg_replace ( "/{phps+(.+)}/", "", $str );
        //alex fix
        $str = preg_replace ( "/{{ifs+(.+?)}}/", "``if \1``", $str );
        $str = preg_replace ( "/{{else}}/", "``else``", $str );
        $str = preg_replace ( "/{{/if}}/", "``/if``", $str );

        $str = preg_replace ( "/{ifs+(.+?)}/", "", $str );
        $str = preg_replace ( "/{else}/", "", $str );
        $str = preg_replace ( "/{elseifs+(.+?)}/", "", $str );
        $str = preg_replace ( "/{/if}/", "", $str );

        //for 循环
        $str = preg_replace("/{fors+(.+?)}/","",$str);
        $str = preg_replace("/{/for}/","",$str);
        //++ --
        $str = preg_replace("/{++(.+?)}/","",$str);
        $str = preg_replace("/{--(.+?)}/","",$str);
        $str = preg_replace("/{(.+?)++}/","",$str);
        $str = preg_replace("/{(.+?)--}/","",$str);
        //alex fix
        $str = preg_replace ( "/``ifs+(.+?)``/", "{{if \1}}", $str );
        $str = preg_replace ( "/``else``/", "{{else}}", $str );
        $str = preg_replace ( "/``/if``/", "{{/if}}", $str );

        $str = preg_replace ( "/{loops+(S+)s+(S+)}/", "", $str );
        $str = preg_replace ( "/{loops+(S+)s+(S+)s+(S+)}/", " \3) { ?>", $str );
        $str = preg_replace ( "/{/loop}/", "", $str );
        $str = preg_replace ( "/{([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff:]*(([^{}]*)))}/", "", $str );
        $str = preg_replace ( "/{\$([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff:]*(([^{}]*)))}/", "", $str );
        $str = preg_replace ( "/{(\$[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)}/", "", $str );
        $str = preg_replace("/{(\$[a-zA-Z0-9_[]'"$x7f-xff]+)}/es", "$this->addquote('')",$str);
        $str = preg_replace ( "/{([A-Z_x7f-xff][A-Z0-9_x7f-xff]*)}/s", "", $str );
        $str = preg_replace("/{pc:(w+)s+([^}]+)}/ie", "self::pc_tag('$1','$2', '$0')", $str);
        $str = preg_replace("/{/pc}/ie", "self::end_pc_tag()", $str);
        $str = "" . $str;
        return $str;
    }

    /**
     * 转义 // 为 /
     *
     * @param $var    转义的字符
     * @return 转义后的字符
     */
    public function addquote($var) {
        return str_replace ( "\"", """, preg_replace ( "/[([a-zA-Z0-9_-.x7f-xff]+)]/s", "['\1']", $var ) );
    }

    /**
     * 解析PC标签
     * @param string $op 操作方式
     * @param string $data 参数
     * @param string $html 匹配到的所有的HTML代码
     */
    public static function pc_tag($op, $data, $html) {
        preg_match_all("/([a-z]+)=["]?([^"]+)["]?/i", stripslashes($data), $matches, PREG_SET_ORDER);
        $arr = array('action','num','cache','page', 'pagesize', 'urlrule', 'return', 'start','setpages');
        $tools = array('json', 'xml', 'block', 'get');
        $datas = array();
        $tag_id = md5(stripslashes($html));
        //可视化条件
        $str_datas = 'op='.$op.'&tag_md5='.$tag_id;
        foreach ($matches as $v) {
            $str_datas .= $str_datas ? "&$v[1]=".($op == 'block' && strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2])) : "$v[1]=".(strpos($v[2], '$') === 0 ? $v[2] : urlencode($v[2]));
            if(in_array($v[1], $arr)) {
                $$v[1] = $v[2];
                continue;
            }
            $datas[$v[1]] = $v[2];
        }
        $str = '';
        $setpages = isset($setpages) && intval($setpages) ? intval($setpages) : 10;
        $num = isset($num) && intval($num) ? intval($num) : 20;
        $cache = isset($cache) && intval($cache) ? intval($cache) : 0;
        $return = isset($return) && trim($return) ? trim($return) : 'data';
        if (!isset($urlrule)) $urlrule = '';
        if (!empty($cache) && !isset($page)) {
            $str .= '$tag_cache_name = md5(implode('&','.self::arr_to_html($datas).').''.$tag_id.'');if(!$'.$return.' = tpl_cache($tag_cache_name,'.$cache.')){';
        }
        if (in_array($op,$tools)) {
            switch ($op) {
                case 'json':
                        if (isset($datas['url']) && !empty($datas['url'])) {
                            $str .= '$json = @file_get_contents(''.$datas['url'].'');';
                            $str .= '$'.$return.' = json_decode($json, true);';
                        }
                    break;

                case 'block':
                    $str .= '$block_tag = pc_base::load_app_class('block_tag', 'block');';
                    $str .= 'echo $block_tag->pc_tag('.self::arr_to_html($datas).');';
                    break;
            }
        } else {
            if (!isset($action) || empty($action)) return false;
            if ( file_exists(APPPATH.'libraries'.DIRECTORY_SEPARATOR.$op.'_tag.php')) {
                $str .= 'if(!isset($CI))$CI =& get_instance();$CI->load->library("'.$op.'_tag");if (method_exists($CI->'.$op.'_tag, ''.$action.'')) {';   
                if (isset($start) && intval($start)) {
                    $datas['limit'] = intval($start).','.$num;
                } else {
                    $datas['limit'] = $num;
                }
                if (isset($page)) {
                    $str .= '$pagesize = '.$num.';';
                    $str .= '$page = intval('.$page.') ? intval('.$page.') : 1;if($page<=0){$page=1;}';
                    $str .= '$offset = ($page - 1) * $pagesize;$urlrule="'.$urlrule.'";';
                    $datas['limit'] = '$offset.",".$pagesize';
                    $datas['action'] = $action;
                    $str .= '$'.$op.'_total = $CI->'.$op.'_tag->count('.self::arr_to_html($datas).');';

                    $str .= 'if($'.$op.'_total>$pagesize){ $pages = pages($'.$op.'_total, $page, $pagesize, $urlrule); } else { $pages="" ;}';
                }
                $str .= '$'.$return.' = $CI->'.$op.'_tag->'.$action.'('.self::arr_to_html($datas).');';
                $str .= '}';
            }
        }
        if (!empty($cache) && !isset($page)) {
            $str .= 'if(!empty($'.$return.')){setcache($tag_cache_name, $'.$return.', 'tpl_data');}';
            $str .= '}';
        }
        return "";
    }

    /**
     * PC标签结束
     */
    static private function end_pc_tag() {
        return '';}?>';
    }

    /**
     * 转换数据为HTML代码
     * @param array $data 数组
     */
    private static function arr_to_html($data) {
        if (is_array($data)) {
            $str = 'array(';
            foreach ($data as $key=>$val) {
                if (is_array($val)) {
                    $str .= "'$key'=>".self::arr_to_html($val).",";
                } else {
                    if (strpos($val, '$')===0) {
                        $str .= "'$key'=>$val,";
                    } else {
                        $str .= "'$key'=>'".self::new_addslashes($val)."',";
                    }
                }
            }
            return $str.')';
        }
        return false;
    }

    /**
     * 返回经addslashes处理过的字符串或数组
     * @param $string 需要处理的字符串或数组
     * @return mixed
     */
    function new_addslashes($string){
        if(!is_array($string)) return addslashes($string);
        foreach($string as $key => $val) $string[$key] = new_addslashes($val);
        return $string;
    }
}

然后在global_helper中增加一个 template函数
复制代码 代码如下:
if ( ! function_exists('template'))
{
    /**
     * 模板调用
     *
     * @param $module
     * @param $template
     * @param $istag
     * @return unknown_type
     */
    function template($module = 'expatree', $template = 'index', $style = 'expatree',$return_full_path=true) {
        global $CI;
        if(!isset($CI))$CI =& get_instance();
        if(!$style) $style = 'default';
        $CI->load->library('template_威尼斯登录首页,cache','template_cache');
        $template_cache = $CI->template_cache;
        //编译模板生成地址
        $compiledtplfile = $template_cache->cache_path.DIRECTORY_SEPARATOR.'caches_template'.DIRECTORY_SEPARATOR.$style.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.$template.EXT;
        //视图文件
        $tplfile= APPPATH.'views'.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.$template.EXT;
        if(file_exists($tplfile)) {
            if(!file_exists($compiledtplfile) || (@filemtime($tplfile) > @filemtime($compiledtplfile))) {   
                $template_cache->template_compile($module, $template, $style);
            }
        } else {
            //如果没有就调取默认风格模板
            $compiledtplfile = $template_cache->cache_path.DIRECTORY_SEPARATOR.'caches_template'.DIRECTORY_SEPARATOR.'default'.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.$template.EXT;
            if(!file_exists($compiledtplfile) || (file_exists($tplfile) && filemtime($tplfile) > filemtime($compiledtplfile))) {
                $template_cache->template_compile($module, $template, 'default');
            } elseif (!file_exists($tplfile)) {
                show_error($tplfile ,  500 ,  'Template does not exist(0)');
            }
        }

        if($return_full_path)
            return $compiledtplfile;
        else
            return 'caches_template'.DIRECTORY_SEPARATOR.$style.DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.$template;
    }
}

然后在MY_Controller.php,增加一个方法
复制代码 代码如下:
/**
    * 自动模板调用
    *
    * @param $module
    * @param $template
    * @param $istag
    * @return unknown_type
    */
   protected function view($view_file,$page_data=false,$cache=false)
   {
       $view_file=$this->template($this->page_data['controller_name'].$this->page_data['module_name'],$view_file);

       $this->load->view($view_file,$page_data);
   }

这样基本上完成了,可以直接phpcms模板语法了。

本文由威尼斯在线注册平台发布于热门新闻,转载请注明出处:比较phpcms的view模板分析就强多数了,接待高手帮小编校勘一下

上一篇:没有了 下一篇:没有了
猜你喜欢
热门排行
精彩图文