我有第三方软件包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 /模板。
如果没有对父母的这种访问,我会发现自己逐字复制整个原始模板文件,然后更新它的一小部分,这只是感觉不对。
答案 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
与提供的路径连接,可以解决每个命名空间的完整路径。