tp6模板block多继承修复(测试)

浏览:294 发布日期:2020/04/23 分类:ThinkPHP6专区 关键字: block,tp6,thinkphp6,block嵌套
如题,目前我自己使用暂时没有发现什么问题,一起交流下看看怎么改进。
模板文件位置为:\vendor\topthink\think-template\src\Template.php。

由于模板继承(extend)只能解析一次block正好今天遇到这个问题就顺手研究了一下,修复后可使用如下代码{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);
        }
    }
上传不了附件,可以自行按照代码修改测试。
最佳答案
评论( 相关
后面还有条评论,点击查看>>