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

yce*_*uto 3 symfony twig

我需要遵循 Symfony 的内置约定之一来覆盖来自第三方包的模板。Symfony 文档讨论了它们:

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

您还可以使用包继承来覆盖包内的模板。有关更多信息,请参阅如何使用 Bundle 继承来覆盖 Bundle 的部分内容

虽然这种方法可能有效,但如果您只需要覆盖模板的一小部分(例如某些块),它可能会过于复杂。此外,如果第三方捆绑包更新了自己的模板,您的模板版本可能会过时,需要更新才能与最新更改保持同步。

这就是我尝试做的但没有成功的事情:

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

{% block title %}My Default Title{% endblock %}
Run Code Online (Sandbox Code Playgroud)

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

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


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

yce*_*uto 5

为什么它不起作用?

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

{% block title %}My Default Title{% endblock %}
Run Code Online (Sandbox Code Playgroud)

原因来自于 Twig 的路径和命名空间在包、它们的子包之间的自动配置以及 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 
Run Code Online (Sandbox Code Playgroud)

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

因此,要覆盖它,您必须/Blog/layout.html.twig在(第 1)或(第 2)路径中创建此模板 ( )。但是,如果您@AcmeBlog/Blog/layout.html.twig同时进行扩展(考虑从原始模板进行扩展),则 Twig 会执行与之前相同的过程,从而导致循环模板引用(无限循环)并且永远不会到达(第三条)路径。

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

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
Run Code Online (Sandbox Code Playgroud)

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

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

{% block title %}My Default Title{% endblock %}
Run Code Online (Sandbox Code Playgroud)

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


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