让你的thinkphp支持嵌套继承模板

来源:互联网 发布:微信小程序案例源码 编辑:程序博客网 时间:2024/05/30 04:21

最近想把后台重写一下,不想再用iframe了,用整页跳转的,当然想到的就是把之前那些固定的菜单做成一个模板,然后挖坑,内容页就填充到坑里


thinkphp里面有模板继承的功能 extend,可我发现它居然不支持嵌套继承


比如我写一个只加载bootstrap框架的basic页basic.html(放在Common/View/Boot/basic.html)

<!DOCTYPE html><html><head><meta charset="utf-8" /><!--<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />--><meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,minimum-scale =1,user-scalable=no" /><link rel="stylesheet" href="{$Think.PLUGIN_PATH}bootstrap/css/bootstrap.min.css" /><link rel="stylesheet" href="{$Think.CSS_PATH}lc.css" /><block name="head"></block></head><body><block name="body"></block><script src="{$Think.PLUGIN_PATH}jquery/jquery-1.11.3.min.js"></script><script src="{$Think.PLUGIN_PATH}bootstrap/js/bootstrap.min.js"></script><block name="foot"></block></body></html>

然后我再写一个我后台的admin_basic.html,继承刚才的basic页(放在Admin/View/Public/admin_basic.html),然后写导航、菜单,然后再挖坑。

<extend name="Common@Boot:basic" /><block name="body"><div id="warpper"><nav>顶部的导航</nav>        <!-- 这儿用tp的Widget扩展读取菜单 -->        <div id="page_menu">{:W("Admin/getAction")}</div><div id="page-warpper"><block name="body">内容页</block></div></div></block><block name="foot"><block name="foot"></block></block>

然后我就写后台管理系统的首页 index.html

<extend name="Public:admin_basic" /><block name="body">这是我的后台系统管理</block><block name="foot"><script type="text/javascript">$(function(){alert("hello,world");});</script></block>

tp它居然默认无法这样实现,我觉得这个功能应该是非常重要的呀,没办法,它不实现,只能我来实现了。

当然首先就是百度了,非常幸运,让我找到下面这个大湿的博客

http://blog.csdn.net/wangzuxi/article/details/44217355

具体是找到Thinkphp/Libray/Think/Template.class.php文件,在245行附近的parseExtend方法中 $content = $this->replaceBlock($content);这句后面增加 $content = $this->parseExtend($content); 让tp递归解析extend,然后再到340行附近的replaceBlock方法中,将  $content = $content[3]; 索引改为0。

请看下在代码,注释有[2develop]

protected function parseExtend($content) {        $begin      =   $this->config['taglib_begin'];        $end        =   $this->config['taglib_end'];                // 读取模板中的继承标签        $find       =   preg_match('/'.$begin.'extend\s(.+?)\s*?\/'.$end.'/is',$content,$matches);        if($find) {            //替换extend标签            $content    =   str_replace($matches[0],'',$content);            // 记录页面中的block标签            preg_replace_callback('/'.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/is', array($this, 'parseBlock'),$content);            // 读取继承模板            $array      =   $this->parseXmlAttrs($matches[1]);            $content    =   $this->parseTemplateName($array['name']);            $content    =   $this->parseInclude($content, false); //对继承模板中的include进行分析            // 替换block标签            $content = $this->replaceBlock($content);            // [2DEVELOP] 支持多层继承            $content = $this->parseExtend($content);        }else{            $content    =   preg_replace_callback('/'.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.'(.*?)'.$begin.'\/block'.$end.'/is', function($match){return stripslashes($match[2]);}, $content);        }        return $content;    }  private function replaceBlock($content){                static $parse = 0;        $begin = $this->config['taglib_begin'];        $end   = $this->config['taglib_end'];        $reg   = '/('.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.')(.*?)'.$begin.'\/block'.$end.'/is';              if(is_string($content)){            do{                $content = preg_replace_callback($reg, array($this, 'replaceBlock'), $content);                            } while ($parse && $parse--);            return $content;        } elseif(is_array($content)){            if(preg_match('/'.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.'/is', $content[3])){ //存在嵌套,进一步解析                $parse = 1;                $content[3] = preg_replace_callback($reg, array($this, 'replaceBlock'), "{$content[3]}{$begin}/block{$end}");                                return $content[1] . $content[3];            } else {                $name    = $content[2];                //[2DEVELOP] 支持多层继承,将下面原来的索引值3改为0                $content = $content[0];                $content = isset($this->block[$name]) ? $this->block[$name] : $content;                return $content;            }        }    }

我用它上面写的方法后,发现真的成功了,但是!可能我比较纠结,我发现了一个小问题。

我发现如果我basic里面的block的name名为body的话,我在admin_basic里如果也挖了一个坑name也为body的话,它就会覆盖admin_basic里我在body的block里写的内容了,要不就得避免block的name值一样。


我比较龟毛,一般主体我一直喜欢用body,所以我不能妥协!


让我研究了一上午,终于让我解决了


到Thinkphp/Libray/Think/Template.class.php

将345附近的$reg   = '/('.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.')(.*?)'.$begin.'\/block'.$end.'/is';

改成下面这个

$reg   = '/('.$begin.'block\sname=[\'"]([^\'"]+?)[\'"]\s*?'.$end.')([^(?!'.$begin.'block)]*?)'.$begin.'\/block'.$end.'/is';


</pre><pre name="code" class="php"> private function replaceBlock($content){                static $parse = 0;        $begin = $this->config['taglib_begin'];        $end   = $this->config['taglib_end'];        //$reg   = '/('.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.')(.*?)'.$begin.'\/block'.$end.'/is';        // [2DEVELOP]支持多层继承,上面是原来的正则        $reg   = '/('.$begin.'block\sname=[\'"]([^\'"]+?)[\'"]\s*?'.$end.')([^(?!'.$begin.'block)]*?)'.$begin.'\/block'.$end.'/is';        if(is_string($content)){            do{                $content = preg_replace_callback($reg, array($this, 'replaceBlock'), $content);                            } while ($parse && $parse--);            return $content;        } elseif(is_array($content)){            if(preg_match('/'.$begin.'block\sname=[\'"](.+?)[\'"]\s*?'.$end.'/is', $content[3])){ //存在嵌套,进一步解析                $parse = 1;                $content[3] = preg_replace_callback($reg, array($this, 'replaceBlock'), "{$content[3]}{$begin}/block{$end}");                                return $content[1] . $content[3];            } else {                $name    = $content[2];                $content = $content[3];                $content = isset($this->block[$name]) ? $this->block[$name] : $content;                return $content;            }        }    }

我也不知这样改会不会有什么错误,不过我看了我其它页面都还没发现有错误的现象,仅供参考学习。


0 0