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

Php 从Symfony/Twig中的过度版本访问父模板,php,symfony,inheritance,twig,bundle,Php,Symfony,Inheritance,Twig,Bundle,我有一个第三方bundleOriginalBundle,我想定制其中的一些模板 为了实现这一点,我使用设置了一个Symfony bundleMyCustomBundle 然后我得到一个白色的死亡屏幕。我猜这会导致某种递归,因为Symfony正在将extends回调路由回自定义文件 原始捆绑包的模板如下所示: {# MyCustomBundle:Foo:bar.html.twig #} {% extends 'OriginalBundle:Foo:bar.html.twig' %} {% bl

我有一个第三方bundle
OriginalBundle
,我想定制其中的一些模板

为了实现这一点,我使用设置了一个Symfony bundle
MyCustomBundle

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

原始捆绑包的模板如下所示:

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

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

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
{# OriginalBundle:Foo:bar.html.twig #}

{% block abc %}
    {% block xyz %}
        {# ... code in here ... #}
    {% endblock %}
{% endblock %}
{# MyCustomBundle:Foo:bar.html.twig #}

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
所以问题是

当同一模板存在过度使用的版本时,是否有办法访问原始模板文件

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


没有这种对父级的访问,我发现自己逐字复制了整个原始模板文件,然后更新了其中的一小部分,这感觉不对劲。

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

{{ parent() }}

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

在中,您希望保留对原始包的“扩展”,您必须使用方法a)因此创建app/Resources/original bundle/views/layout.html.twig和/或app/Resources/original bundle/views/Foo/bar.html.twig,但粘贴这些模板供应商文件的整个代码,因为您希望重用它们(默认情况下供应商视图会覆盖这些路径)然后你可以使用你的“扩展”

如果您还希望覆盖供应商的控制器,则使用方法b):但即使在这种情况下,您也必须粘贴要重用的代码(并且必须在新捆绑包上进行“扩展”)


因为我习惯于覆盖控制器,所以我使用方法b。抱歉,这是不可能的。如果你计划覆盖控制器,请始终使用方法a)和方法b。实际上,我正在搜索相同的内容。 我的用例如下所示:

我有一个带有仪表板的网站。我想用捆绑包中的新数据扩展仪表板。 每个包都有自己的数据,我想放在仪表板的某些块中。 仪表板模板未绑定到任何捆绑包,因此应该可以访问

我想知道如何在不重载任何路由的情况下将块注入模板


编辑:导航栏也一样,例如-应该有一种方法可以毫无问题地扩展块,这样就可以轻松地从捆绑包中扩展主网站导航…

您是否尝试过这样做:

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

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

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
{# OriginalBundle:Foo:bar.html.twig #}

{% block abc %}
    {% block xyz %}
        {# ... code in here ... #}
    {% endblock %}
{% endblock %}
{# MyCustomBundle:Foo:bar.html.twig #}

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
没有扩展部分?

有一个解决方案。 默认情况下,Symfony搜索第一个匹配的资源并返回它。 要更改此行为,需要指定一些附加语法。我用“!”进入第二场比赛

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

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}
覆盖文件可以位于
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;
        }
    }
}

此问题是由于Symfony将对
原始bundle
的模板引用解释为
ChildBundle
,这是由于bundle继承导致函数嵌套级别异常

您可以使用以下符号引用父级的捆绑包模板文件:

{% extends "@Original/Foo/bar.html.twig" %}
代替:

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

Twig的
文件系统加载器
将引用字符串拆分为名称空间(原始)和路径(Foo/bar.html.Twig)。Namespace是不带bundle后缀的bundle名称。通过将默认的
/Resources/views/
与提供的路径连接,可以解析每个命名空间的完整路径

你也可以显示你扩展的原始模板吗?当然-我已经编辑了这个问题,添加了一个example@caponica,我想您正在寻找“嵌入”细枝功能。这对我来说是新功能-我明天会看一看。但我不确定这是否有帮助,因为我正在尝试覆盖(第三方)捆绑包的模板。我认为嵌入也没有帮助。。。此场景是一个Symfony bundle覆盖,它将
OriginalBundle:Foo:bar.html.twig
的使用路由到同一文件的自定义版本。我想知道的是,是否有办法访问原始文件(从我的自定义模板),也就是说,有选择地忽略孩子自己模板中的过度使用。我不认为是这样。。。我想扩展模板并重新定义其中的一个块,但对其他所有内容都使用父块定义
parent()
用于渲染父块,这不是我要做的。(另外,我重新定义的块不是空的-请注意,白色屏幕是由于symfony崩溃造成的。)您能显示原始和自定义控制器以及细枝文件的路径吗。。。里面有密码吗?我觉得没关系。。。引用是正确的,如果我不尝试扩展原始文件,或者如果我只是扩展一个模板而不使用Symfony的
getParent()
bundle override系统,它就可以工作。但当我尝试使用这两种方法时,我被卡住了。。。这就是问题所在。我已经更新了它,用getParent()调用显示over ride类。路径是:
project\src\My\CustomBundle\MyCustomBundle.php
project\src\My\CustomBundle\Resources\views\Foo\bar.html.twig
project\vendor\third-party\original bundle\Resources\views\Foo\bar.html.twig
对不起,这不是解决方案。这说明了问题所在。如果我使用方法(a),那么我必须粘贴源代码的整个代码。这个问题是关于如何扩展原始文件并在我的版本中添加新的位。Ohhh..我从来没有见过这样做的文档…我想你不能,因为正如fosuserbundle文档和symfony文档中所解释的那样,当你扩展模板时,默认情况下它会首先在app/Resources中显示,然后在捆绑包的src中显示,不在供应商中。。。您可以在应用程序/资源中尝试,而无需使用“扩展”到di