让你的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; } } }
我也不知这样改会不会有什么错误,不过我看了我其它页面都还没发现有错误的现象,仅供参考学习。
- 让你的thinkphp支持嵌套继承模板
- 让nginx完美支持Thinkphp的配置
- ThinkPHP示例:模板继承
- ThinkPHP模板多层继承
- thinkphp模板继承小结
- thinkPHP 5 模板继承
- 让ThinkPHP的Page.class.php支持简短分页路由
- 让Nginx支持ThinkPHP的URL重写和PATHINFO
- 如何让ThinkPHP的模板引擎达到最佳效率
- 让你的程序支持插件
- 如何让你的网站支持SSL
- 让你的软件支持繁体中文
- 让你的软件支持繁体中文
- 让你的软件支持繁体中文
- 让你的工程支持MFC
- 【原创】让你的JSP支持Ubbcode
- 让你的Firefox支持Windows Media
- 让你的Firefox支持Windows Media
- 最小生成树 Kruscal算法--poj 2377
- SQL查询重复数据和清除重复数据
- c socket 单线程多用户并发
- hibernate 实现多表联合查询
- 修改linux系统默认字符编码
- 让你的thinkphp支持嵌套继承模板
- Git 使用方法
- iOS开发 -- 延时执行某个方法的几种方式的比较和汇总
- android json解析及简单例子
- 进程与线程的一个简单解释---有趣的例子(转)
- Zigbee网关 Zstack开启AES加密
- iOS-上传程序错误:Your build settings specify a provisioning profile with the UUID, no provisioning profile
- 音效与音乐
- mmap---关于读写文件