如何管理依赖项自动加载

时间:2011-09-09 14:10:58

标签: php autoload

构建库时,我总是提供一个Autoloader类来处理库的自动加载。自动加载器的注册如下:

require_once 'path/to/PHP-Parser/lib/PHPParser/Autoloader.php';
PHPParser_Autoloader::register();

如果我的库依赖于另一个库,我不确定如何处理它。想象一下,PHPParser取决于PHPLexer。现在使用库时,需要编写:

require_once 'path/to/PHP-Lexer/lib/PHPLexer/Autoloader.php';
PHPLexer_Autoloader::register();

require_once 'path/to/PHP-Parser/lib/PHPParser/Autoloader.php';
PHPParser_Autoloader::register();

如果只有一个依赖项或依赖项本身具有依赖项,则可能会很快变得混乱。

那么如何处理依赖关系自动加载?

我的一个想法是,库也应该为它的依赖关系处理自动加载,但这感觉不对。另一个想法是根本不提供自动加载器并假设人们使用UniversalClassLoader。虽然这似乎也不正确。

3 个答案:

答案 0 :(得分:8)

嗯,有几种方法可以解决这个问题,每种方法各有利弊:

  1. 为所有库使用通用的PSR-0自动加载器,并在初始化时注册其他项目的位置。

    • 优点:
      1. 实施起来非常简单
      2. 使用相同的代码,因此只能使用一个自动加载器
      3. 您可以注册应用程序引导程序文件中的所有路径,以便在一个位置定义所有库自动加载
    • 缺点
      1. 要求所有库实现与PSR-0兼容的文件结构
      2. 稍微泄漏抽象级别,因为应用程序引导程序需要引导应用程序内的所有内容,包括每个单独的库。
      3. 将库的文件结构紧密耦合到自动加载器(如果库实现了一个冲突的新文件,即使它们的工作文件也会破坏自动加载器)
  2. 为每个库定义自定义自动加载器。

    • 优点
      1. 实施起来非常简单。
      2. 在库中保留库自动加载语义。
      3. 由于职责分离而提供更好的可维护代码
    • 缺点
      1. 你的bootstrap文件中有很多硬编码的类(虽然不是很重要)
      2. 自动加载类必须通过多个自动加载器才能实现性能
      3. 泄漏抽象级别,因为库可能需要更多的努力来引导而不仅仅是自动加载
  3. 为每个库实现bootstrap.php(最好由库提供)

    • 优点
      1. 实施起来非常简单。
      2. 在库中保留库自动加载语义
      3. 由于关注点分离而提供更好的代码
      4. 能够定义非平凡的库引导代码而不会使应用程序的其他部分混淆
    • 缺点
      1. 仍需要require_once '/path/to/lib/dir/bootstrap.php';初始化
      2. 性能(与第二种解决方案相同的原因)
      3. 大多数3pd库没有实现引导文件,因此您可能需要维护一个。
  4. 就个人而言,我使用第三种选择。一个例子是我的CryptLib库中的bootstrap.php file。要初始化它,只需调用bootstrap。您也可以使用任何PSR-0自动加载器,只是不要调用bootstrap.php,它会正常工作。但是使用bootstrap选项,如果我添加了在启动时注册自身的功能,我可以将它添加到bootstrap.php文件中并自动执行(而不是告诉用户他们需要执行“x,y” ,z“启动时”......

    关于你提到的通用类加载器选项(不带参数调用spl_autoload_register()),我个人不喜欢这个选项。首先,它降低了类名(它违反了PSR-0,我不喜欢它。我已经习惯了区分大小写的类 - >路径映射,现在实际上更喜欢它)。其次,它总是使用相对路径,因此它将击败大多数操作码缓存。还有其他问题,但那些是大问题......

答案 1 :(得分:2)

如果按PSR-0约定命名的库中的类,则可以为所有库使用一个自动加载器。否则,库应该提供自己的自动加载器。

答案 2 :(得分:-1)

添加到类构造函数

public function __construct(){
$this->Register();
}

之后在您要加载的页面上创建一个对象

$obj = new PHPParser_Autoloader();