概述
最近想把后台重写一下,不想再用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.'extends(.+?)s*?/'.$end.'/is',$content,$matches);
if($find) {
//替换extend标签
$content = str_replace($matches[0],'',$content);
// 记录页面中的block标签
preg_replace_callback('/'.$begin.'blocksname=['"](.+?)['"]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.'blocksname=['"](.+?)['"]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.'blocksname=['"](.+?)['"]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.'blocksname=['"](.+?)['"]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.'blocksname=['"](.+?)['"]s*?'.$end.')(.*?)'.$begin.'/block'.$end.'/is';
改成下面这个
$reg = '/('.$begin.'blocksname=['"]([^'"]+?)['"]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.'blocksname=['"](.+?)['"]s*?'.$end.')(.*?)'.$begin.'/block'.$end.'/is';
// [2DEVELOP]支持多层继承,上面是原来的正则
$reg = '/('.$begin.'blocksname=['"]([^'"]+?)['"]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.'blocksname=['"](.+?)['"]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;
}
}
}
我也不知这样改会不会有什么错误,不过我看了我其它页面都还没发现有错误的现象,仅供参考学习。
最后
以上就是碧蓝短靴为你收集整理的让你的thinkphp支持嵌套继承模板的全部内容,希望文章能够帮你解决让你的thinkphp支持嵌套继承模板所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复