最近想把后台重写一下,不想再用iframe
了,用整页跳转的,当然想到的就是把之前那些固定的菜单做成一个模板,然后挖坑,内容页就填充到坑里,thinkphp
里面有模板继承的功能 extend
,可我发现它居然不支持嵌套继承。
比如我写一个只加载bootstrap
框架的basic页basic.html
(放在Common/View/Boot/basic.html)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <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),然后写导航、菜单,然后再挖坑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<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
1 2 3 4 5 6 7 8 9 10 11 |
<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]
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
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’;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
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; } } } |
我也不知这样改会不会有什么错误,不过我看了我其它页面都还没发现有错误的现象,仅供参考学习。