无论如何都可以在 Composer 中使用自定义自动加载器吗?
我有一些包含数百个类的库,它们按照 PSR-0 排列在目录结构中。
然而,它们也包括一个静态构造器(类似于 Java 的静态初始化器)。
我在作曲家之前使用的自动加载器会:
if (method_exists($class, '__static')) {
call_user_func(array($class, '__static'));
}
那么有没有办法扩展作曲家的默认自动加载器来做到这一点?
无论如何都可以在 Composer 中使用自定义自动加载器吗?
我有一些包含数百个类的库,它们按照 PSR-0 排列在目录结构中。
然而,它们也包括一个静态构造器(类似于 Java 的静态初始化器)。
我在作曲家之前使用的自动加载器会:
if (method_exists($class, '__static')) {
call_user_func(array($class, '__static'));
}
那么有没有办法扩展作曲家的默认自动加载器来做到这一点?
您可以通过修改ClassLoader.php
(在供应商目录中找到)来破解 Composer 的自动加载器以支持此功能:
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
include $file;
// Added your custom code:
if (method_exists($class, '__static')) {
call_user_func(array($class, '__static'));
}
return true;
}
}
但是这个文件每次运行都会更新composer update
(源码包含在里面composer.phar
),所以修改一次也不好;您需要一种使这种修改“永久”的方法。
我能想到的有两种方法:
该解决方案涉及修改composer.phar
,这意味着:
composer self-update
会用最新的官方版本覆盖修改过的 Composer 源码,撤销 hack我编写了一个简短的 PHP 脚本,它在 Composer 源上执行有针对性的查找/替换;它只会修改它所针对的确切代码,这意味着您每次都需要在未修改的 Composer 版本上运行它(它会拒绝触及已经修改的版本):
<?php
if (!Phar::canWrite()) {
die ('The config setting phar.readonly must be set to 0 in php.ini');
}
$phar = new Phar('composer.phar');
$fileName = 'src/Composer/Autoload/ClassLoader.php';
try {
$source = file_get_contents($phar[$fileName]);
}
catch (BadMethodCallException $e) {
echo $e->getMessage();
die;
}
$find = <<<'END_ORIGINAL'
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
include $file;
return true;
}
}
END_ORIGINAL;
$replaceWith = <<< 'END_REPLACEMENT'
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
include $file;
// Add your custom code here!
return true;
}
}
END_REPLACEMENT;
$find = preg_replace('/\s+/', '\\s+', preg_quote($find));
$modified = preg_replace('/'.$find.'/', $replaceWith, $source);
if ($source == $modified) {
echo 'Could not find replacement target, aborting';
die;
}
file_put_contents($phar[$fileName], $modified);
echo 'Replacement done, file saved';
Composer 允许您将脚本附加到您的根包;一个修改后的更新脚本ClassLoader.php
是一个很好的方法,可以使更改在更新中保持不变,同时保持 Composer 的源完整。
调整上一节中的代码来执行此操作非常简单。理想情况下,脚本将是一个静态 PHP 类方法,但为了做到这一点,您必须创建一个新的 Composer 包,该包使用 Composer 的 PSR-0 自动加载器自动加载,因为该类必须自动加载,目前无法使用类映射自动加载类在 Composer 的更新过程中。
无论文件如何加载(自动加载、显式要求或包含),一个更安全的替代方法是在类定义之后简单地调用静态初始化器:
class Foo {
private static $__constructed = false;
public static function __static() {
if (self::$__constructed) return;
// do initialization
self::$__constructed = true;
}
}
Foo::__static();
我最终做的是:
vendor/composer/ClassLoader.php
git checkout vendor/composer/ClassLoader.php
后composer update