覆盖 symfony 3rd 方包资源

override symfony 3rd party bundle resource

Symfony 2.7.5

问题

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

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

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

这让我可以更改某些 FOS 用户 class 成员的可见性。它使我无需任何其他配置即可完成此操作。甚至不是儿童-class 设置。

目前已尝试

我看过this,但它只讲基本资源。

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

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

我想不出在这种情况下成功使用继承来完成我需要做的事情的方法。由于相关文件未在供应商捆绑包本身之外引用。

问题(已编辑)

有什么方法可以 extend/override 一个包 class 文件,放在这样的目录结构中?我不需要接触太多的包,但我真的需要得到这个文件。这是摘自 APYDataGridBundle.

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

您可以使用 Composer 的自动加载功能来完成此操作。

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

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

怎么做

在你的 composer.json 中应该有这样一个部分:

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

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

如果像这样更改块:

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

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

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

当然,你甚至不必将命名空间与你的目录结构相匹配,你也可以做类似 src/replacements/grid.php 的事情,如果这对你来说更好的话。只需确保文件中的 namespace 声明是正确的。

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

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

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

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

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

如果将来您发现需要重写 class 并且无法通过这些方法之一完成,您可以随时创建自己的捆绑包分支,尽管这很痛苦并且很难维护,所以我只会在你找不到其他选择的情况下推荐它