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

时间:2014-07-30 13:32:58

标签: php symfony inheritance twig bundle

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

为实现这一目标,我使用the override method shown in the Symfony docs设置了Symfony包MyCustomBundle

<?php

namespace My\CustomBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class MyCustomBundle extends Bundle
{
    public function getParent()
    {
        return 'OriginalBundle';
    }
}

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

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

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

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

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}

然后我得到一张白色的死亡画面。我猜它会引起某种递归,因为Symfony将extends调用路由回自定义文件?

原始包的模板如下所示:

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

{% block abc %}
    {% block xyz %}
        {# ... code in here ... #}
    {% endblock %}
{% endblock %}

所以问题......

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

我基本上在寻找等同于parent::doSomething()的Twig /模板。

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

7 个答案:

答案 0 :(得分:6)

有一个解决方案。 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;
        }
    }
}

并在app / AppKernel.php

中使用它
class AppKernel extends \Webility\Bundle\WebilityBundle\HttpKernel\Kernel

答案 1 :(得分:3)

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

{{ parent() }}

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

答案 2 :(得分:3)

你有没有试过这样做:

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

{% block xyz %}
    {# ... code in here ... #}
{% endblock %}

没有延伸部分?

答案 3 :(得分:2)

如果你想保留你的'扩展'到原始包,你必须使用方法a)所以创建app / Resources / original-bundle / views / layout.html.twig和/或app / Resources / original-bundle /views/Foo/bar.html.twig但是通过粘贴这些模板供应商文件的整个代码,因为您想要重复使用它们(这些路径会覆盖供应商的默认视图)然后您可以使用'' 延伸

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

因为我习惯于覆盖控制器,所以使用方法b

答案 4 :(得分:1)

很抱歉,但不能......总是做方法a)和b如果你打算覆盖控制器

答案 5 :(得分:1)

我实际上在寻找相同的东西。 我的用例如下:

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

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

编辑:导航栏的相同内容,例如 - 应该有一种扩展块没有任何问题的方法,所以很容易从捆绑中扩展主网站导航......

答案 6 :(得分:1)

此问题是由Symfony将您对backgroundPosition的模板引用解释为OriginalBundle而导致函数嵌套级别异常的捆绑继承所致。

您可以使用以下表示法引用父代的包模板文件:

ChildBundle

取代:

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

Twig的{% extends "OriginalBundle:Foo:bar.html.twig" %} 将引用字符串拆分为命名空间(原始)和路径(Foo / bar.html.twig)。命名空间是没有Bundle后缀的包名称。通过将默认FilesystemLoader与提供的路径连接,可以解决每个命名空间的完整路径。