跳到内容

如何覆盖 Bundle 的任何部分

编辑此页

当使用第三方 bundle 时,你可能想要自定义或覆盖它的某些功能。本文档描述了覆盖 bundle 最常用功能的方法。

模板

第三方 bundle 模板可以在 <your-project>/templates/bundles/<bundle-name>/ 目录中被覆盖。新的模板必须使用与原始模板相同的名称和路径(相对于 <bundle>/templates/)。

例如,要覆盖来自 AcmeUserBundle 的 templates/registration/confirmed.html.twig 模板,请创建此模板:<your-project>/templates/bundles/AcmeUserBundle/registration/confirmed.html.twig

警告

如果你在一个新的位置添加了一个模板,你*可能*需要清除你的缓存 (php bin/console cache:clear),即使你处于 debug 模式。

除了覆盖整个模板,你可能只想覆盖一个或多个块。然而,由于你正在覆盖你想要扩展的模板,你最终会陷入无限循环错误。解决方案是在模板名称中使用特殊的 ! 前缀,以告诉 Symfony 你想要从原始模板扩展,而不是从被覆盖的模板扩展。

1
2
3
4
5
6
7
{# templates/bundles/AcmeUserBundle/registration/confirmed.html.twig #}
{# the special '!' prefix avoids errors when extending from an overridden template #}
{% extends "@!AcmeUser/registration/confirmed.html.twig" %}

{% block some_block %}
    ...
{% endblock %}

提示

Symfony 内部也使用了一些 bundle,所以你可以应用相同的技术来覆盖核心 Symfony 模板。例如,你可以通过覆盖 TwigBundle 模板来自定义错误页面

路由

路由永远不会在 Symfony 中自动导入。如果你想包含来自任何 bundle 的路由,那么它们必须从你的应用程序中的某个位置手动导入(例如 config/routes.yaml)。

“覆盖” bundle 路由的最简单方法是完全不导入它。与其导入第三方 bundle 的路由,不如将该路由文件复制到你的应用程序中,修改它,然后导入它。

控制器

如果控制器是一个服务,请参阅下一节关于如何覆盖它。否则,定义一个新的路由 + 控制器,其路径与你想要覆盖的控制器关联(并确保新的路由在 bundle 路由之前加载)。

服务 & 配置

如果你想修改 bundle 创建的服务,你可以使用服务装饰

如果你想进行更高级的操作,例如删除其他 bundle 创建的服务,你必须在编译器 pass中使用服务定义

实体 & 实体映射

只有当 bundle 提供映射的父类(例如 FOSUserBundle 中的 User 实体)时,覆盖实体映射才有可能。可以通过这种方式覆盖属性和关联。在Doctrine 文档中了解更多关于此功能及其限制的信息。

表单

现有的表单类型可以通过定义表单类型扩展来修改。

验证元数据

Symfony 从每个 bundle 加载所有验证配置文件,并将它们组合成一个验证元数据树。这意味着你可以向属性添加新的约束,但你不能覆盖它们。

为了克服这个问题,第三方 bundle 需要为验证组进行配置。例如,FOSUserBundle 就有这个配置。要创建你自己的验证,请将约束添加到新的验证组

1
2
3
4
5
6
7
8
9
10
# config/validator/validation.yaml
FOS\UserBundle\Model\User:
    properties:
        plainPassword:
            - NotBlank:
                groups: [AcmeValidation]
            - Length:
                min: 6
                minMessage: fos_user.password.short
                groups: [AcmeValidation]

现在,更新 FOSUserBundle 配置,使其使用你的验证组而不是原始的验证组。

翻译

翻译与 bundle 无关,而是与翻译域有关。因此,你可以从主 translations/ 目录覆盖任何 bundle 翻译文件,只要新文件使用相同的域。

例如,要覆盖在 AcmeUserBundle 的 translations/AcmeUserBundle.es.yaml 文件中定义的翻译,请创建一个 <your-project>/translations/AcmeUserBundle.es.yaml 文件。

这项工作,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
TOC
    版本