{extend name="base/frame" /}
{block name="head"}
{block name="base_css"}{/block}
{block name="css"}{/block}
{block name="base_js"}{/block}
{block name="js"}{/block}
{/block}
{block name="body"}
{block name="base_main"}
{include file="base/page-head" /}
{block name="main"}{/block}
{include file="base/footer" /}
{/block}
{block name="base_bottom"}{/block}
{block name="bottom"}{/block}
{:hook('bottom')}
{/block}修改代码如下:新增2个方法,改进模板的parseExtend方法 /**
* 修复parent值被替换
* @param $blocks
* @param $_blocks
* @return array
*/
private function mergeBlock(&$blocks, $_blocks)
{
if (is_array($blocks)) {
foreach ($_blocks as $_block => $_values) {
if (array_key_exists($_block, $blocks)) {
$blocks[$_block]['content'] = $_values['content'];
} else {
$blocks[$_block] = $_values;
}
}
} else {
$blocks = [];
}
return $blocks;
}
/**
* 替换嵌套的block
* @param $blocks
* @param string $pKey
* @param string $key
* @return mixed
*/
private function updateBlocks(&$blocks, $pKey = '', $key = '')
{
$begin = $this->config['tpl_begin'];
$end = $this->config['tpl_end'];
if (empty($pKey) && empty($key)) {
foreach ($blocks as $k => $v) {
if (!empty($blocks[$k]['parent'])) {
$this->updateBlocks($blocks, $blocks[$k]['parent'], $k);
}
}
} else {
if (isset($blocks[$pKey]) && isset($blocks[$key])) {
$pBlock = &$blocks[$pKey];
$block = &$blocks[$key];
$search = "/{$begin}block name=\"{$key}\"{$end}[\s\S]*?{$begin}\/block{$end}/";
$replace = $block['content'];
$pBlock['content'] = preg_replace($search, $replace, $pBlock['content']);
if (!empty($pBlock['parent'])) {
$this->updateBlocks($blocks, $pBlock['parent'], $key);
}
}
}
return $blocks;
}
/**
* 解析模板中的extend标签
* @access private
* @param string $content 要解析的模板内容
* @return void
*/
private function parseExtend(string &$content): void
{
$regex = $this->getRegex('extend');
$array = $blocks = $baseBlocks = [];
$extend = '';
$func = function ($template) use (&$func, &$regex, &$array, &$extend, &$blocks, &$baseBlocks) {
if (preg_match($regex, $template, $matches)) {
if (!isset($array[$matches['name']])) {
$array[$matches['name']] = 1;
// 读取继承模板
$extend = $this->parseTemplateName($matches['name']);
// 递归检查继承
$func($extend);
// 取得block标签内容
$blocks = $this->mergeBlock($blocks, $this->parseBlock($template));//修复点1
return;
}
} else {
// 取得顶层模板block标签内容
$baseBlocks = $this->parseBlock($template, true);
if (empty($extend)) {
// 无extend标签但有block标签的情况
$extend = $template;
}
}
};
$func($content);
$blocks = $this->updateBlocks($blocks);//修复点2
if (!empty($extend)) {
if ($baseBlocks) {
$children = [];
foreach ($baseBlocks as $name => $val) {
$replace = $val['content'];
if (isset($children[$name]) && is_array($children[$name])) {
// 如果包含有子block标签
foreach ($children[$name] as $key) {
$replace = str_replace($baseBlocks[$key]['begin'] . $baseBlocks[$key]['content'] . $baseBlocks[$key]['end'], $blocks[$key]['content'], $replace);
}
}
if (isset($blocks[$name])) {
// 带有{__block__}表示与所继承模板的相应标签合并,而不是覆盖
$replace = str_replace(['{__BLOCK__}', '{__block__}'], $replace, $blocks[$name]['content']);
if (!empty($val['parent'])) {
// 如果不是最顶层的block标签
$parent = $val['parent'];
if (isset($blocks[$parent])) {
$blocks[$parent]['content'] = str_replace($blocks[$name]['begin'] . $blocks[$name]['content'] . $blocks[$name]['end'], $replace, $blocks[$parent]['content']);
}
$blocks[$name]['content'] = $replace;
$children[$parent][] = $name;
continue;
}
} elseif (!empty($val['parent'])) {
// 如果子标签没有被继承则用原值
$children[$val['parent']][] = $name;
$blocks[$name] = $val;
}
if (!$val['parent']) {
// 替换模板中的顶级block标签
$extend = str_replace($val['begin'] . $val['content'] . $val['end'], $replace, $extend);
}
}
}
$content = $extend;
unset($blocks, $baseBlocks);
}
}上传不了附件,可以自行按照代码修改测试。
ThinkPHP 是一个免费开源的,快速、简单的面向对象的 轻量级PHP开发框架 ,创立于2006年初,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业应用开发而诞生的。ThinkPHP从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,也注重易用性。并且拥有众多的原创功能和特性,在社区团队的积极参与下,在易用性、扩展性和性能方面不断优化和改进,已经成长为国内最领先和最具影响力的WEB应用开发框架,众多的典型案例确保可以稳定用于商业以及门户级的开发。