黑客作曲家
您可以通过修改 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 本身
这个解决方案涉及修改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 允许您将scripts 附加到您的根包;修改 ClassLoader.php 的更新后脚本是一种在保持 Composer 源完整的同时使更改持续更新的好方法。
修改上一节中的代码来执行此操作非常简单。理想情况下,脚本应该是一个静态 PHP 类方法,但为了做到这一点,您必须创建一个新的 Composer 包,该包使用 Composer 的 PSR-0 自动加载器自动加载,因为该类必须自动加载,目前它是not possible 在 Composer 更新过程中使用类映射自动加载类。