【问题标题】:Why Isn't Using Namespaces for Autoloading Bad Practice?为什么不使用命名空间来自动加载不好的做法?
【发布时间】:2013-06-23 00:04:17
【问题描述】:

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

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

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

如果您根据 Form 类所在的命名空间自动加载,您是否会遇到命名空间旨在防止的确切问题:类和方法的模棱两可的标识符?

当您成功地在 MySweetForms 命名空间中找到另一个类(例如 AjaxFileField,它依赖于 \MySweetForms\Form,但它找到了 FormBuilderForm 类的实现时,它不会失败吗?

【问题讨论】:

  • 好问题.....也有兴趣听到答案! :)

标签: php namespaces autoloader psr-0


【解决方案1】:

由于命名空间,自动加载在寻找MySweetForms 实现时将找不到FormBuilderForm 类实现,前提是自动加载器和两个库遵循最佳(或接近最佳) ) 实践并正确实施。

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

namespace MySweetForms;

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

那么AjaxFileField 内部对Form 类的引用实际上是完全限定类名MySweetForms\Form 的简写。

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

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

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

关键是要认识到实际上没有两个Form 类——一个类的完全限定名称为FormBuilder\Core\Form,一个类的完全限定名称为MySweetForms\Form——和一个正确实施的自动加载器会期望它们位于完全不同的位置,并且不会尝试加载一个文件来代替另一个文件。

命名空间和基于命名空间将文件组织到目录中的 PSR 风格相结合,可以很容易地重复使用常用词而不会引起冲突,并将完全限定的类名可预测地映射到相应的文件。

将类名解析为完全限定的类名是这一点的关键,并在 PHP 手册中进行了讨论(命名空间常见问题解答有几点: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

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 2012-02-13
    • 2021-06-29
    • 2012-04-20
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    相关资源
    最近更新 更多