如何告诉 Composer 从文件中加载给定命名空间下的所有内容?

How to tell Composer to load everything under a given namespace from a file?

我正在使用解析器生成器生成一个长文件(~35000 行)文件,其中包含多个 PHP classes 和函数。该文件如下所示:

<?php
namespace foo;

if (function_exists("foo\bar") {
  function bar() {
    // ...
  }
}

if (class_exists("foo\Baz") {
  class Baz {
    // ...
  }
}

// other classes and functions declared in a similar manner.

这与 Composer 的自动加载机制配合得不是很好,它更喜欢:

  1. 加载包含单个 class 的文件,方法是在 autoload.psr-4 中定义它。
  2. 每当 vendor/autoload.phprequire 时加载整个文件,方法是在 autoload.files
  3. 中定义它

我想尽可能推迟加载这个文件,因为这个文件很重,每次请求都加载它会给服务器带来很大的负担。

我在这里要做的是让 Composer 仅在我的代码中的其他地方引用其命名空间 foo 时才加载文件。

我该怎么做?

您可以创建一个额外的自动加载器,它只会处理您特定命名空间中的 classes:

// composer's autoloader
require dirname( __DIR__ ) . '/vendor/autoload.php';

// your own thing
spl_autoload_register(function ($class_name)
    {
        if (strpos($class_name, 'foo') !== 0) {
            return;
        }
        include_once 'path_to_your_generated_autoloader.php';
    }
);

(为方便起见,我使用匿名函数,但实际使用什么取决于您)。

只有 foo 命名空间上的 class 才会命中您生成的文件。一旦命中,所有 classes 和函数都会被定义,所以这个自动加载器不会再次被命中。如果 class 不在 foo 命名空间中,它将 return 无害。

但是你还是有问题。

您生成的文件似乎包含 命名空间函数(例如 foo\bar())。 函数没有自动加载。因此,如果您在尝试在 foo 命名空间上加载 class 之前调用 foo\bar() before,就会遇到麻烦。 (如果您只是在使用任何 class 之后才尝试使用这些函数,您会没事的;因为届时文件中的所有内容都会被加载)。

如果您想将您的函数保留在任何 class 之外,没有办法绕过它。也许您应该将这些函数生成为单个 "helper" class 的静态方法,例如 foo\Helper::bar()。但这可能需要您更改代码生成的工作方式。