我正在使用 Codeigniter 和 Composer。要求之一是 PHPExcel。现在我需要更改其中一个类中的函数。最好的策略应该是什么?我应该更改供应商文件夹中的代码吗?如果是这样,如何维护所有实例的更改?如果不是,我如何覆盖该特定类。虽然我提到了 PHPExcel,但我想要一个通用的解决方案。
我不确定这是否是解决这个问题的正确论坛。如果没有我会删除这个。如果需要更多详细信息,请告诉我。
谢谢你。
在composer.json中的[“autoload”][“psr-4”]下,添加一个以命名空间为键、路径为值的条目:
{
"autoload": {
"psr-4": {
"BuggyVendor\\Namespace\\": "myfixes/BuggyVendor/Namespace"
}
}
}
将要覆盖的文件复制到该路径下(保留子命名空间目录结构)并在那里编辑它们。它们将优先于库包的原始“类路径”被选择。似乎以这种方式添加到composer.json 的命名空间->路径映射会在所需包添加的映射之前被考虑。注意:我刚刚尝试过并且有效,但我不知道这是否是预期的功能或可能存在的问题。
编辑:发现了一个问题。有时,当您随后需要带有
composer require vendor/package
的另一个包时,您将“丢失”覆盖。如果发生这种情况,您必须手动发出 composer dump-autoload
。这将恢复正确的自动加载顺序,以尊重您的覆盖。
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
。
还有一种选择。 如果您需要重写唯一的类,您可以在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
的实现。
您也可以简单地复制文件并用您自己的文件覆盖原始文件。假设创建一个目录,例如“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');\""
]
}
更改现有类违反 OOP 和 SOLID 原则(特别是开放扩展/封闭修改原则)。所以这里的解决方案不是直接更改代码,而是扩展代码以添加您的功能。
在理想的世界中,您永远不应该更改不属于您的代码。 事实上,使用 Composer 则不能,因为更新依赖项时您的更改将被覆盖。
您的情况的解决方案是在应用程序级别创建一个类,并扩展您想要更改的类(位于库级别)以用您的代码覆盖。如果您不知道如何操作,请查看在 PHP 中扩展类。
然后,通常,您加载您的类而不是他们的类,这样,您可以在其功能之上添加您的功能,并且在更新的情况下,不会中断任何内容(如果是非中断更新)。