我已经看到了一些使用PSR对命名空间进行自动加载的示例。也许这是一个愚蠢的问题,但为什么不是这种不好的做法?这不是打败了命名空间的目的吗?
例如,假设您有两个库,FormBuilder
和MySweetForms
,并且都有Form
类。地点位于:
lib/FormBuilder/Core/Form.php
和lib/MySweetForms/Form.php
如果您根据这些Form
类所在的命名空间进行自动加载,那么您是否会遇到名称空间要防止的确切问题:类和方法的模糊标识符?
当您在MySweetForms
命名空间中成功找到另一个依赖于AjaxFileField
的{{1}}的类时,它是否会失败,但它会找到\MySweetForms\Form
的FormBuilder
类的实现?
答案 0 :(得分:0)
由于名称空间,自动加载在查找FormBuilder
实现时找不到Form
类的MySweetForms
实现,前提是自动加载器和两个库如下最佳(或接近最佳)实践并正确实施。
如果MySweetForms/AjaxFileField.php
文件在MySweetForms
命名空间内定义了一个类,如下所示:
namespace MySweetForms;
class AjaxFileField
{
public function doFormStuff()
{
$form = new Form();
}
}
然后对Form
内AjaxFileField
类的引用实际上是完全限定类名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