Custom Composer Autoloader

Pet*_*tah 2 php static constructor autoloader composer-php

无论如何使用Composer的自定义自动加载器?

我有一些包含数百个类的库,它们按照PSR-0布局在目录结构中.

但是它们还包括一个静态构造函数(类似于Java的静态初始化程序).

我在编剧之前使用的自动加载器会:

if (method_exists($class, '__static')) {
    call_user_func(array($class, '__static'));
}
Run Code Online (Sandbox Code Playgroud)

那么有没有扩展Composers默认自动加载器也这样做呢?

Jon*_*Jon 5

黑客作曲家

您可以通过修改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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,每次运行时都会更新此文件composer update(源包含在内部composer.phar),因此进行一次修改并不是很好; 你需要一种方法使这种修改"永久".

有两种方法我可以想到:

修改Composer本身

此解决方案涉及修改composer.phar,这意味着:

  • 执行修改后,黑客将始终生效,无需任何其他设置
  • 运行composer self-update将使用最新的正式版本覆盖修改后的Composer源,撤消黑客攻击

我编写了一个简短的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';
Run Code Online (Sandbox Code Playgroud)

使用更新后的脚本

Composer允许您将脚本附加到根包; 修改后更新脚本ClassLoader.php是一种很好的方法,可以使更改保持更新,同时保持Composer的源不变.

调整上一节中的代码来完成此操作非常简单.理想情况下,脚本将是一个静态PHP类方法,但为了做到这一点,您必须创建一个新的Composer包,使用Composer的PSR-0自动加载器自动加载,因为该类必须自动加载,目前无法使用类映射自动加载类在Composer的更新过程中.