【问题标题】:Can PSR-0 class autoloader, load PEAR library?PSR-0 类自动加载器,可以加载 PEAR 库吗?
【发布时间】:2012-10-01 10:42:36
【问题描述】:

所以这是我的问题,我编写了属于 PSR-0 标准的自己的类自动加载器。这很简单。现在我有了我的 PHP MVC Frameowrk,我想使用 Twig,但是 Twig 不使用使用 _ 而不是 \ 的 PEAR 命名标准。

现在 PSR-0 自动加载器是否也应该能够加载 PEAR 库? 因为在那些自动加载器内部_ 被转换为\? 如果我注册它,我的加载器无法加载 Twig,但可能是我在某个地方犯了错误。

PSR-0 兼容的类加载器也应该能够加载 PEAR 库吗?

【问题讨论】:

标签: php pear autoload psr-0


【解决方案1】:

PSR-0 兼容的类加载器也应该能够加载 PEAR 库吗?

是的,PSR-0 可与类和文件的 PEAR 命名约定互操作。

这不再公开记录,但众所周知。

如果您无法加载类,则说明您的自动加载器不符合 PSR-0。

Double-Check with the specification。您还将找到与 PSR-0 兼容的 SplClassLoader class linked there,您可以使用它来代替您自己的。

一个可能更好的加载器是The Symfony2 ClassLoader Component。您可以通过 Pear 或 Composer (symfony/class-loader on Packagist) 轻松安装它。

如果您编写自己的类加载器,请注意使用spl_autoload_register,请参阅


奖励功能:

spl_autoload_register 的行为与 PHP 中一样,但 PSR-0 分辨率包含路径:

$spl_autoload_register_psr0 = function ($extensions = null) {
    $callback = function ($className, $extensions = null) {
        if (!preg_match('~^[a-z0-9\\_]{2,}$~i', $className)) {
            return;
        }
        null !== $extensions || $extensions = spl_autoload_extensions();
        $extensions = array_map('trim', explode(',', $extensions));
        $dirs = array_map('realpath', explode(PATH_SEPARATOR, get_include_path()));

        $classStub = strtr($className, array('_' => '/', '\\' => '/'));

        foreach ($dirs as $dir) {
            foreach ($extensions as $extension) {
                $file = sprintf('%s/%s%s', $dir, $classStub, $extension);
                if (!is_readable($file)) {
                    continue;
                }
                include $file;
                return;
            }
        }
    };
    return spl_autoload_register($callback);
};

var_dump(get_include_path());
var_dump(spl_autoload_extensions());
var_dump($spl_autoload_register_psr0());

【讨论】:

  • 是的,我正在使用 spl_autoload_register 和 spl_autoload_unregister。我的 Autoload 不兼容,但现在是 :) 我已经得到了答案,PEAR 和 PSR0 的唯一区别应该是命名空间分隔符。为您和您的努力 +1!
  • @otporan:不,你错了。 PSR-0 支持 _ 作为开箱即用的伪命名空间分隔符。阅读规格。您首先创建了一个 PSR-0 不兼容的类加载器。
  • 不,你错了。 PSR-0 不支持 PEAR 自动加载。我用你在你的答案中链接的 SplClassLoader 来测试测试器。假设要加载 PEAR 的 Twig,您不能这样做: $classLoader = new SplClassLoader('Twig', '../vendor'); $classLoader->register();它不起作用,但如果你像这样更改命名空间分隔符: $classLoader->setNamespaceSeparator('_');然后就可以了。 PSR-0 声明你应该在你的类名中更改 _ 为 DIRECTORY_SEPERATOR。但这还不足以让 loadclass 方法知道文件在哪里,这就是为什么你必须告诉你使用什么 NS!
  • 并以 Smyfony2 UniversalClassLoader 为例,您可以清楚地区分如何注册 PSR0 和 PEAR 包。甚至 UniversalClassLoader findFile 方法通过执行以下操作检查当前类是否具有 PE​​AR 或 PSR0 标准: if (false !== $pos = strrpos($class, '\\')) { // PSR0 } else { PEAR } 而我没有想检查我的负载类中的标准。我想要 2 个类加载器实例,一个用于 PSR0,另一个用于 PEAR,唯一的区别是 _ 与 \,可以通过 setNS 方法设置,就像在您链接的 SplClassLoader 中一样。感谢您的帮助。
  • @otporan:但这并没有改变PSR-0 specs 的任何含义,没有区别。如果您说您创建了与 PSR-0 兼容的东西,那么它必须同时支持两种方式。正如你在你的问题中要求的那样,我回答了它。除了标准之外,您可以做任何您想做的事情,但是您不应该将其称为 PSR-0 兼容。请参阅规范的强制部分。
【解决方案2】:

PSR-0 应该能够使用完全限定的命名空间和带下划线的类。您需要做的就是用目录分隔符替换下划线。一个很好的例子是:

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName  = '';
    $namespace = '';
    if ($lastNsPos = strripos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName  = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';

    require $fileName;
}

希望这会有所帮助!

【讨论】:

  • 感谢您的回复!答案是肯定的! :) PSR-0 兼容的类加载器可以加载 PEAR 库。真棒!我对自动加载类所做的是,我可以为 PSR0 实例化一个类,为 PEAR 实例化一个类。 PSR-0 和 PEAR 的唯一区别是命名空间分隔符。所以我向我的自动加载类添加了可以更改默认命名空间分隔符的方法。 $autoload->setNS('\\') 用于 PSR-0,$autoload->setNS('_') 用于 PEAR,它就像一个魅力 :) 嗯!再次感谢,你让我想到了正确的方式!
  • @otporan:你很可能这样做是错误的。我已经添加了一个答案,请查看 Symfony2 加载程序并具体查看 UniversalClassLoader
  • @otporan 你不应该真的需要设置一个 setNS 函数,因为斜杠和下划线都应该转换为目录分隔符。我假设您在字符串替换中使用 setNS 函数中定义的字符串,只需将其替换为 array('\\', '_') 就可以了
猜你喜欢
  • 2015-01-08
  • 2019-12-22
  • 2014-02-14
  • 2013-11-09
  • 2014-08-02
  • 2014-07-25
  • 2014-04-16
  • 2012-09-05
  • 2023-01-31
相关资源
最近更新 更多