覆盖使用Composer安装的库中的类的策略

时间:2015-01-23 06:58:06

标签: php codeigniter composer-php

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

我不确定这是否是这个问题的正确论坛。如果不是我将删除此。如果需要更多细节,请告诉我。

谢谢。

4 个答案:

答案 0 :(得分:30)

在composer.json中,在[“autoload”] [“psr-4”]下,添加一个以namespace作为键的路径,并将路径作为值:

{
     "autoload": {

         "psr-4": {

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

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

编辑:发现了一个问题。有时,当您随后需要另一个包含composer require vendor/package的包时,您将“丢失”覆盖。如果发生这种情况,您必须手动发出composer dump-autoload。这将恢复正确的自动加载顺序,以兑现您的覆盖。

答案 1 :(得分:5)

还有一个选择。 如果你需要重写唯一的类,你可以在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的实现。

答案 2 :(得分:0)

在我的autoload的{​​{1}}部分中添加最后两行,这对于我只想覆盖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

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

答案 3 :(得分:-3)

更改现有类是针对OOP和SOLID原则(特定于修改原则的Open to extension / Closed)。因此,这里的解决方案不是直接更改代码,而是扩展代码以添加功能。

在一个理想的世界中,你永远不应该改变你不拥有的代码。 事实上,使用编辑器是不可能的,因为在更新依赖项时,您的更改将被覆盖。

在您的情况下,解决方案是在应用程序级别创建一个类,并扩展您要更改的类(在库级别)以覆盖您的代码。如果你不知道怎么做,请查看用PHP扩展课程。

然后通常,你加载你的类而不是他们的类,这样,你在功能上添加你的功能,并且在更新的情况下,没有任何中断(如果没有更新的中断)。