为什么不使用命名空间进行自动加载不良操作?

时间:2013-06-26 01:19:03

标签: php namespaces autoloader psr-0

我已经看到了一些使用PSR对命名空间进行自动加载的示例。也许这是一个愚蠢的问题,但为什么不是这种不好的做法?这不是打败了命名空间的目的吗?

例如,假设您有两个库,FormBuilderMySweetForms,并且都有Form类。地点位于:

lib/FormBuilder/Core/Form.phplib/MySweetForms/Form.php

如果您根据这些Form类所在的命名空间进行自动加载,那么您是否会遇到名称空间要防止的确切问题:类和方法的模糊标识符?

当您在MySweetForms命名空间中成功找到另一个依赖于AjaxFileField的{​​{1}}的类时,它是否会失败,但它会找到\MySweetForms\FormFormBuilder类的实现?

1 个答案:

答案 0 :(得分:0)

由于名称空间,自动加载在查找FormBuilder实现时找不到Form类的MySweetForms实现,前提是自动加载器和两个库如下最佳(或接近最佳)实践并正确实施。

如果MySweetForms/AjaxFileField.php文件在MySweetForms命名空间内定义了一个类,如下所示:

namespace MySweetForms;

class AjaxFileField
{
    public function doFormStuff()
    {
        $form = new Form();
    }
}

然后对FormAjaxFileField类的引用实际上是完全限定类名MySweetForms\Form的简写。

当调用自动加载器加载类时,将要求它根据它的完全限定名称加载该类。 PSR-0自动加载器会将MySweetForms\Form类名转换为MySweetForms/Form.php路径,并且(如果它被告知要查看lib目录)它会找到正确的文件。如果该文件丢失,自动加载器最终将失败。类似地,如果该文件定义了Form类但忽略了提供命名空间,则实际的类(MySweetForms\Form)将不存在(相反,全局类Form会) - 这不会t匹配AjaxFileField类中引用的类的完全限定名称,因此会发生错误。

请注意,如果代码包含$form = new \FormBuilder\Core\Form();,则类名已经完全限定,并且将要求自动加载器加载FormBuilder\Core\Form类(并且期望它在FormBuilder/Core/Form.php类中{1}}文件)。

如果我们使用了$form = new \Form();,我们将引用全局命名空间中的Form类,并会要求自动加载器查找Form(它会在{{1}中查找此时直接在Form.php文件夹中的文件。)

关键是要认识到实际上没有两个lib类 - 有一个类具有完全限定名称Form,另一个类具有完全限定名{{1} - 并且正确实现的自动加载器会将它们放在完全不同的位置,并且不会尝试加载一个文件来代替另一个文件。

命名空间和基于命名空间将文件组织到目录中的PSR样式的组合使得在不引起冲突的情况下重用常用词非常容易,并且可以预测地将完全限定的类名映射到相应的文件。

将类名解析为完全限定的类名是关键,并在PHP手册中讨论(命名空间FAQ有几点关于它:http://www.php.net/manual/en/language.namespaces.faq.php)。 PSR-0标准本身也是一个有用的参考:https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md