我正在使用一个解析器生成器,它吐出一个长文件(~35000行)文件,其中包含多个PHP类和函数。该文件如下所示:
<?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 的自动加载机制不太配合,后者更喜欢:
- 加载包含单个类的文件,方法是在
autoload.psr-4
中定义它。 - 每当
require
vendor/autoload.php
时加载整个文件,方法是在autoload.files
中定义它
我想尽可能推迟此文件的加载,因为该文件非常繁重,并且在每个请求上加载它会给服务器带来相当大的负担。
我在这里要做的是让 Composer 仅在其命名空间foo
在我的代码中的其他地方被引用时才加载文件。
我该怎么做?
您可以创建一个额外的自动加载器,该加载器将仅处理特定命名空间中的类:
// 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
命名空间上的类时,才会命中生成的文件。一旦命中,所有类和函数都将被定义,因此此自动加载器不会再次命中。如果类不在foo
命名空间上,它将无害地返回。
但是你仍然有问题。
似乎您生成的文件包含命名空间函数(例如foobar()
)。并且没有函数的自动加载。因此,如果您在尝试在foo
命名空间上加载类之前调用foobar()
,那么您会遇到麻烦。(如果你只是在使用任何类后尝试使用这些函数,那你就可以了;因为到那时文件中的所有内容都会被加载)。
如果你想把你的函数保留在任何类之外,这是没有办法的。也许您应该将这些函数生成为单个"帮助程序"类的静态方法,例如fooHelper::bar()
.但这可能需要您更改代码生成的工作方式。