自定义自动加载与作曲家的自动加载冲突?



我有一个PHP项目,它加载一个名为custom_funcs.php的引导程序文件,该文件位于根Web目录中。此文件包含一堆函数,定义了多个常量,并执行以下操作:

require dirname( __DIR__ ) . '/lib/php/vendor/autoload.php';
spl_autoload_register( function ($class_name) { include __DIR__ ."/classes/$class_name.php"; });
set_include_path( get_include_path() . PATH_SEPARATOR . SITEROOT );

第一行加载编辑器自动加载器。(请注意,作曲家库位于根 Web 目录之外)。第二行告诉我的代码在哪里查找无法识别的类,这样我就不必不断地手动加载我曾经使用的类文件。 第三行将 Web 根目录添加到 PHP 的 PATH 中。

几年来,它与几个作曲家包一起运行良好。

然后。。。我安装了PhpUnit。 总的来说,我工作正常,除了我运行测试时:

  1. 如果没有错误,则正常工作。
  2. 如果有错误,我也会收到PHP警告:
Warning: include(C:...path_to_web_root.../classes/SebastianBergmannInvokerInvoker.php): failed to open stream: No such file or directory in C:...path_to_web_root...common_funcs.php on line 14
Warning: include(): Failed opening 'C:...path_to_web_root.../classes/SebastianBergmannInvokerInvoker.php' for inclusion (include_path='xxxxxxx') in C:...path_to_web_root...common_funcs.php on line 14

所以PhpUnit正在尝试自动加载一个名为"Invoker"的类,但代码使用的是我自己设置的自动加载路径spl_autoload_register

有没有办法解决这个问题? 这是PhpUnit中的一个错误吗?

我可以通过在包含行之前使用"@"来隐藏错误,但我不惜一切代价避免@hiding错误

注意:我在通过以下方式测试之前加载custom_funcs.php

public static function setUpBeforeClass(): void {
require 'common_funcs.php';
}

文件结构可能会使其更清晰:

c:/some_path/
..lib/
....php/
......vendor/
........(third-party Composer libraries)
..webroot/
....custom_funcs.php
....classes/
......(namespace)/
........(my custom classes)

我正在使用命名空间:MyCompanyPortal. 所以我的自定义类可以在<webroot>/classes/MyCompany/Portal/中找到

最简单的方法是修复您的自动加载器 - 如果自动加载器无法加载类,则不应抛出此类错误。 在这种情况下,什么都不做是正确的操作:

spl_autoload_register(function ($class_name) {
if (file_exists(__DIR__ . "/classes/$class_name.php")) {
include __DIR__ . "/classes/$class_name.php";
return true;
}
});

您可以在composer.json中将自定义自动加载器函数替换为classmap自动加载器:

{
"autoload": {
"classmap": ["classes/"],
"files": ["custom_funcs.php"]
}
}

此映射是通过扫描给定目录/文件中所有.php.inc文件中的类来构建的。

每当创建新类时,可能都必须使用composer dump-autoload更新作曲家的自动加载器才能选取它。不过,我不确定默认情况下是这种情况还是仅在优化自动加载器时。无论如何,这都可以通过对新类采用 PSR-0 或 PSR-4 命名约定来解决。

编辑:由于所有文件都将使用作曲家的自动加载器自动加载,因此不再需要手动require它们。因此,您也可以删除setupBeforeClass

方法。

最新更新