从Symfony/Twig中的过载版本访问父模板

cap*_*ica 4 php inheritance bundle symfony twig

我有第三方包OriginalBundle,我想自定义其中的一些模板.

为此,我MyCustomBundle使用Symfony文档中显示的覆盖方法设置了Symfony包.

<?php

namespace My\CustomBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class MyCustomBundle extends Bundle
{
    public function getParent()
    {
        return 'OriginalBundle';
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我使用MyCustomBundle从OriginalBundle创建一些Twig模板的重载版本.但是,我希望能够从我的版本访问原始模板(例如扩展它)并且只是覆盖一些块.

但是,如果我尝试做这样的事情:

{# MyCustomBundle:Foo:bar.html.twig #}

{% extends 'OriginalBundle:Foo:bar.html.twig' %}

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

然后我得到一个白色的死亡屏幕.我猜它会导致某种递归,因为Symfony extends将回调路由回自定义文件?

原始包的模板如下所示:

{# OriginalBundle:Foo:bar.html.twig #}

{% block abc %}
    {% block xyz %}
        {# ... code in here ... #}
    {% endblock %}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

那么问题......

当存在相同模板的过度版本时,有没有办法访问原始模板文件?

我基本上是在寻找相当于Twig /模板的parent::doSomething().

如果没有对父级的这种访问,我发现自己逐字复制整个原始模板文件,然后更新它的一小部分,这只是感觉不对.

Mac*_*ski 6

有一个解决方案.Symfony默认搜索第一个匹配的资源并返回它.要更改此行为,您需要指定一些其他语法.我用 "!" 达到第二场比赛.

{% extends '!OriginalBundle:Foo:bar.html.twig' %}

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

覆盖文件可能在 app/Resources/OriginalBundle/views/Foo/bar.html.twig

要激活此系统,您需要覆盖原始内核:

<?php
namespace Webility\Bundle\WebilityBundle\HttpKernel;

use Symfony\Component\HttpKernel\Kernel as BaseKernel;

abstract class Kernel extends BaseKernel
{
    public function getBundle($name, $first = true)
    {
        $get_next = false;
        if($name[0] == '!' && $first){
            $name = substr($name, 1);
            $first = false;
            $get_next = true;
        }

        $bundles = parent::getBundle($name, $first);

        if($get_next){
            return isset($bundles[1]) ? $bundles[1] : $bundles[0];
        } else {
            return $bundles;
        }
    }

    public function locateResource($name, $dir = null, $first = true)
    {
        $get_next = false;
        if($name[0] == '@' && $name[1] == '!' && $first){
            $name = '@'.substr($name, 2);
            $first = false;
            $get_next = true;
        }

        $files = parent::locateResource($name, $dir, $first);

        if($get_next){
            return isset($files[1]) ? $files[1] : $files[0];
        } else {
            return $files;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并在app/AppKernel.php中使用它

class AppKernel extends \Webility\Bundle\WebilityBundle\HttpKernel\Kernel
Run Code Online (Sandbox Code Playgroud)


小智 3

如果您想保留xyz链接到 的原始捆绑包中的块视图FooController,您必须输入

{{ parent() }}
Run Code Online (Sandbox Code Playgroud)

否则,如果您重新定义内部没有任何内容的块,那么您会得到一个空页面,这是正常的。