【问题标题】:override symfony 3rd party bundle resource覆盖 symfony 3rd 方捆绑资源
【发布时间】:2015-10-31 20:33:15
【问题描述】:

Symfony 2.7.5

问题

我正在尝试覆盖第 3 方供应商文件中的类文件,以便我可以稍微扩展功能。此文件不是服务或控制器的一部分。

相当令人困惑(我不确定为什么会这样),我通过创建如下目录结构覆盖了FOSUserBundle 的一部分:

 src
    │   
    │
    └───FOS
        │   
        │
        ├───Model
            │   User.php
            │   Group.php
            │   ...

这使我能够更改某些 FOS 用户类成员的可见性。它允许我在没有任何其他配置的情况下做到这一点。甚至没有子类设置。

目前尝试过

我读过this,但它只谈论基本资源。

我也读过this,但它似乎只适用于控制器或Resources 文件夹中的任何东西。

我尝试设置一个子包,类似于上面的链接,但无济于事。

我想不出在这种情况下成功使用继承来完成我需要做的事情的方法。因为有问题的文件没有在供应商捆绑包本身之外被引用。

问题(已编辑)

有没有一种方法可以扩展/覆盖位于这样的目录结构中的捆绑类文件?我不需要接触太多的捆绑包,但我真的需要得到这个文件。这是APYDataGridBundle的摘录。

 vendor
    │   
    │
    └───APY
        │   
        │
        ├───datagrid-bundle
            │   
            │   
            ├───Grid
                |
                | .. grid.php <-- this file

【问题讨论】:

  • 如果您告诉我们哪个类在哪个捆绑包中,这可能会有所帮助
  • 我试图覆盖 APYDataGridBundle 中的 grid.php
  • 虽然问题已经解决了,但我还是在这里补充一下——你感兴趣的类被定义为services.xml中带有参数标签的服务。您可以只为参数 grid.class 覆盖类的位置,仅此而已。
  • 啊,好的,是的,这是一个很好的观点。我可能需要覆盖更多内容,因此类映射方式(在这种情况下)可能更灵活。

标签: php symfony bundle


【解决方案1】:

您可以使用 Composer 的自动加载功能来做到这一点。

您可能已经知道,Composer 会在您第一次调用该类时自动加载包含该类的 PHP 文件。所以你不必一直使用require 语句。

为了实现您的目标,您可以“欺骗”自动加载器在每次调用 APY\DataGridBundle\Grid\Grid 时加载一个不同的文件。

怎么做

在您的composer.json 中应该有这样的部分:

"autoload": {
    "psr-4": {
        "": "src/"
    }
},

这将告诉 Composer 你的类在src/ 目录中。但是由于 APYDataGridBundle 已经在 他们的 composer.json 中定义了更具体的命名空间路径,因此自动加载器将永远不会查看您的文件。

如果您像这样更改块:

"autoload": {
    "psr-4": {
        "": "src/"
    },
    "classmap": ["src/APY/DataGridBundle/Grid/Grid.php"]
},

Composer 将分析文件Grid.php 并查找其中的类。然后它会创建一个类映射,这样每当调用其中的类时,它甚至会在检查 PSR-0 或 PSR-4 命名空间路径之前知道要加载哪个文件。

所以基本上,你是在以更高的优先级告诉它文件的路径,以便它首先被加载。

当然,您甚至不必将命名空间与您的目录结构相匹配,如果这对您更好,您也可以执行 src/replacements/grid.php 之类的操作。只需确保文件中的 namespace 声明是正确的。

编辑:更改composer.json 后,您必须执行composer dump-autoload,以便根据新配置生成新的自动加载文件。

【讨论】:

    【解决方案2】:

    一般来说,您只能在以下两种情况之一覆盖捆绑包中的类:

    • 如果 symfony 定义了一种通用的方法来查找这些类,那么您只需在目录中放置一个新类就可以覆盖它们。例如,控制器会发生这种情况。
    • 如果捆绑包通过使用其服务定义中的参数加载此类。在这种情况下,您可以通过在配置文件中设置此参数来覆盖它

    在你的情况下你很幸运,这个包通过它的 services.xml 文件中定义的参数加载这个类,所以你可以通过在你的 config.yml 文件中覆盖这个参数来提供你自己的类:

    # app/config/config.yml
    parameters:
        grid.class: your own class, for example AppBundle/Grid/Grid
    

    如果将来你发现你需要重写一个类并且无法通过这些方法之一来完成,你总是可以创建你自己的包的分支,尽管这很痛苦并且难以维护,所以我只有在没有其他选择的情况下才会推荐它

    【讨论】:

    • 不知道让你覆盖任何类的自动加载器技巧,我注意到了
    猜你喜欢
    • 2015-03-01
    • 2013-06-08
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 2020-11-29
    • 2013-10-07
    相关资源
    最近更新 更多