如何覆盖**部分**第三方模板?

时间:2017-07-20 16:33:29

标签: symfony twig

我需要遵循Symfony的内置约定来覆盖第三方软件包中的模板。 Symfony documentation谈到他们:

  

要覆盖捆绑模板,只需将捆绑包中的index.html.twig模板复制到app/Resources/AcmeBlogBundle/views/Blog/index.html.twigapp/Resources/AcmeBlogBundle目录即将存在,因此您需要创建它)。您现在可以自由地自定义模板。

     

您还可以使用bundle继承覆盖bundle中的模板。有关详细信息,请参阅How to Use Bundle Inheritance to Override Parts of a Bundle

这很有效,但是当我只需要覆盖它的一小部分(例如一些块)时,它就太多了。此外,当第三方软件包更改其自己的模板时,模板将过时,强制我使用最新更改保持更新。

这是我没有成功的尝试:

{# app/Resources/AcmeBlogBundle/views/Blog/layout.html.twig #}
{% extends '@AcmeBlog/Blog/layout.html.twig' %}

{% block title %}My Default Title{% endblock %}

上述代码不起作用。当我访问此页面并且清除缓存命令永远不会结束时,它会在达到最大执行时间后中断。

为什么它不起作用以及如何在不从第三方软件包中复制整个父模板的情况下实现它?

相关问题和没有解决方法的提取请求:

1 个答案:

答案 0 :(得分:4)

  

为什么它不起作用?

{# app/Resources/AcmeBlogBundle/views/Blog/layout.html.twig #}
{% extends '@AcmeBlog/Blog/layout.html.twig' %}

{% block title %}My Default Title{% endblock %}

原因来自Twig的路径和名称空间在bundle,他们的孩子和Symfony的路径约定之间自动配置。默认情况下,Symfony/Bundle/TwigBundle按照以下顺序为所有路径分配相同的Twig的命名空间(AcmeBlog):

# config.yml
twig:
    paths:
        # Auto-configuration behind the scenes for TwigBundle extension:

        # (1st) if AcmeBlogChildBundle has as parent to AcmeBlogBundle
        'src/AcmeBlogChildBundle/Resources/views': AcmeBlog 

        # (2nd) Path to override bundles (Symfony's convention)
        'app/Resources/AcmeBlogBundle/views':      AcmeBlog 

        # (3rd) third-party bundle
        'vendor/acme/blog-bundle/Resources/views': AcmeBlog 

这意味着,如果您需要呈现@AcmeBlog/Blog/layout.html.twig模板,Twig会尝试在名称空间与AcmeBlog匹配的所有路径(按照已定义的顺序)中找到它。

因此,要覆盖它,您必须在(第一个)或(第二个)路径中创建此模板(/Blog/layout.html.twig)。但是,如果您同时从@AcmeBlog/Blog/layout.html.twig延伸(考虑从原始模板扩展),那么Twig执行相同的先前过程,导致循环模板引用(无限循环)并且永远不会到达( 3)路径。

  

如何在不从第三方软件包中复制整个父模板的情况下实现它?

Symfony的内置解决方法

让我们在twig路径配置中为此第三方捆绑包定义不同的Twig命名空间:

# config.yml
twig:
    paths:
        # (4th) third-party bundle alias.
        # The path can be relative to project or real path
        vendor/acme/blog-bundle/Resources/views: AcmeBlogOriginal

稍后,当您覆盖从原始文件扩展的第三方模板时,请使用命名空间别名来避免循环引用:

{# app/Resources/AcmeBlogBundle/views/Blog/layout.html.twig #}
{% extends '@AcmeBlogOriginal/Blog/layout.html.twig' %}

{% block title %}My Default Title{% endblock %}

因此,您可以覆盖整个模板而不是整个模板。即使应该开箱即用,因为它只是关于Twig的路径。

自Symfony 3.4以来,此问题已作为内置功能解决。 http://symfony.com/blog/new-in-symfony-3-4-improved-the-overriding-of-templates#overriding-and-extending-templates