覆盖随 Composer 安装的库中的类的策略

问题描述 投票:0回答:5

我正在使用 Codeigniter 和 Composer。要求之一是 PHPExcel。现在我需要更改其中一个类中的函数。最好的策略应该是什么?我应该更改供应商文件夹中的代码吗?如果是这样,如何维护所有实例的更改?如果不是,我如何覆盖该特定类。虽然我提到了 PHPExcel,但我想要一个通用的解决方案。

我不确定这是否是解决这个问题的正确论坛。如果没有我会删除这个。如果需要更多详细信息,请告诉我。

谢谢你。

php codeigniter composer-php
5个回答
65
投票

在composer.json中的[“autoload”][“psr-4”]下,添加一个以命名空间为键、路径为值的条目:

{
     "autoload": {

         "psr-4": {

             "BuggyVendor\\Namespace\\": "myfixes/BuggyVendor/Namespace"
         }
     }
}

将要覆盖的文件复制到该路径下(保留子命名空间目录结构)并在那里编辑它们。它们将优先于库包的原始“类路径”被选择。似乎以这种方式添加到composer.json 的命名空间->路径映射会在所需包添加的映射之前被考虑。注意:我刚刚尝试过并且有效,但我不知道这是否是预期的功能或可能存在的问题。

编辑:发现了一个问题。有时,当您随后需要带有

composer require vendor/package
的另一个包时,您将“丢失”覆盖。如果发生这种情况,您必须手动发出
composer dump-autoload
。这将恢复正确的自动加载顺序,以尊重您的覆盖。


20
投票
当我只想覆盖

autoload 目录中的一个文件时,

将最后 2 行
添加到我的
composer.json
vendors
部分对我很有用:

"autoload": {        
    "classmap": [
        "database"
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "exclude-from-classmap": ["vendor/somepackagehere/blah/Something.php"],
    "files": ["app/Overrides/Something.php"]
},

请记住,

app/Overrides/Something.php
中的命名空间需要与
vendor/somepackagehere/blah/Something.php
中的原始命名空间相匹配。

编辑完

composer dump-autoload
后记得运行
composer.json

文档:https://getcomposer.org/doc/04-schema.md#files


15
投票

还有一种选择。 如果您需要重写唯一的类,您可以在composer.json中使用files,如下所示

 "autoload": {
     "files": ["path/to/rewritten/Class.php"]
  }

所以如果你想重写类

Some\Namespace\MyClass
这样写

#path/to/rewritten/Class.php

namespace Some\Namespace;

class MyClass {
  #do whatever you want here
}

根据每个请求,作曲家都会将该文件加载到内存中,因此在使用时

Some\Namespace\MyClass
- 将使用
path/to/rewritten/Class.php
的实现。


0
投票

您也可以简单地复制文件并用您自己的文件覆盖原始文件。假设创建一个目录,例如“vendor-overrides”,您可以在其中放置固定文件,只需将其添加到您的作曲家中即可:

"scripts": {
    "post-install-cmd": [
      "@php -r \"copy('vendor-overrides/path/to/your/fixed/file.php', 'vendor/path/to/your/broken/file.php');\""
    ],
    "post-update-cmd": [
"@php -r \"copy('vendor-overrides/path/to/your/fixed/file.php', 'vendor/path/to/your/broken/file.php');\""
    ]
  }

-14
投票

更改现有类违反 OOP 和 SOLID 原则(特别是开放扩展/封闭修改原则)。所以这里的解决方案不是直接更改代码,而是扩展代码以添加您的功能。

在理想的世界中,您永远不应该更改不属于您的代码。 事实上,使用 Composer 则不能,因为更新依赖项时您的更改将被覆盖。

您的情况的解决方案是在应用程序级别创建一个类,并扩展您想要更改的类(位于库级别)以用您的代码覆盖。如果您不知道如何操作,请查看在 PHP 中扩展类。

然后,通常,您加载您的类而不是他们的类,这样,您可以在其功能之上添加您的功能,并且在更新的情况下,不会中断任何内容(如果是非中断更新)。

© www.soinside.com 2019 - 2024. All rights reserved.