自定义自动加载与 Composer 的自动加载冲突?

Custom autoload conflicts with Composer's autoload?

我有一个 PHP 项目,它加载了一个名为 custom_funcs.php 的 bootstrap 文件,该文件位于 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 );

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

几年来,它与几个 Composer 包一起工作得很好。

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

  1. 如果没有错误,则正常。
  2. 如果出现错误,我还会收到 PHP 警告:
Warning: include(C:\...path_to_web_root.../classes/SebastianBergmann\Invoker\Invoker.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/SebastianBergmann\Invoker\Invoker.php' for inclusion (include_path='xxxxxxx') in C:\...path_to_web_root...\common_funcs.php on line 14

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

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

我可以通过在 include 行前使用“@”来隐藏错误,但我会不惜一切代价避免@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)

我正在使用命名空间:MyCompany\Portal。所以我的自定义 classes 在 <webroot>/classes/MyCompany/Portal/

中找到

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

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 autoloader 替换自定义自动加载器函数
{
    "autoload": {
        "classmap": ["classes/"],
        "files": ["custom_funcs.php"]
    }
}

This map is built by scanning for classes in all .php and .inc files in the given directories/files.

每当您创建一个新的 class 时,您可能必须使用 composer dump-autoload 更新作曲家的自动加载器才能将其拾取。不过,我不确定这是默认情况下的情况还是仅在优化自动加载器时出现的情况。无论如何,这可以通过为新的 classes.

采用 PSR-0 或 PSR-4 命名约定来解决。

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