【问题标题】:Is this a good way to use Namespaces in PHP这是在 PHP 中使用命名空间的好方法吗
【发布时间】:2012-01-26 09:55:00
【问题描述】:

前段时间我研究过 PHP 中命名空间的使用,但最近查看了一个使用 use 关键字然后访问命名空间对象的项目,就好像它们在没有命名空间的情况下是正常的一样。

我的问题是,下面的代码是否正确,它是一个文件index.php 并使用命名空间MyLibrary\Base 然后使用use 引入\MyLibrary\Registry \MyLibrary\User\MyLibrary\Request

然后它可以访问这些对象中的任何一个,而无需在它们前面放置命名空间,因此use 部分下面的实际代码看起来像一个普通的前命名空间 php 文件。

我在问你是否这样使用命名空间?还是我错过了什么?

文件:index.php

<?php
namespace MyLibrary\Base;

use \MyLibrary\Registry;
use \MyLibrary\User;
use \MyLibrary\Request;


class Base
{
    public $registry;

    function __construct($registry)
    {
        $this->registry = $registry;
        $this->user = New User;
        $this->request = new Request;
        # code...
    }
}
?>

文件:registry.class.php

<?php
namespace MyLibrary\Registry;

class Registry
{
    public $user;

    function __construct($user)
    {
        $this->user = $user;
        # code...
    }
}
?>

【问题讨论】:

    标签: php namespaces


    【解决方案1】:

    是的。 use-statement 将类名或命名空间名导入当前范围。写这么短的东西就是 PHP-devs 实现命名空间的原因;)

    namespace MyFirstNamespace {
        class Foo {}
    }
    namespace MySecondNamespace {
        use \MyFirstNamespace\Foo as Bar;
        $foo = new Bar;
    }
    

    a) 它使所有内容都更具可读性,因为它比 Vendor_Package_Foo_Bar_XyzClass 短得多,并且 b) 您可以交换类以非常快速地使用。

    # use \MyFirstNamespace\Foo as Bar; // I don't like Foo anymore
    use \MyFirstNamespace\SimilarToFoo as Bar;
    

    【讨论】:

    • 这太棒了,让我现在想使用命名空间,在我真的不想之前,因为我认为我必须在整个代码中处理看起来邪恶的 `\` 分隔符。这让我想起了 Python,你必须导入库的方式
    • 其实我应该说,这就像他们使用的 C#...using System;using System.Collections.Generic; 等等...我只是没有意识到他们正在导入命名空间。我还可以看到使用点/句点作为 NS 分隔符会更好看。
    • 一个简单的问题,就像您发布的 use \MyFirstNamespace\Foo as Bar; 我知道您可以这样更改名称,但是在我看到的代码中,他们像我的示例一样... use \MyFirstNamespace\Foo; 然后访问只需使用Foo 这可能吗?请注意,我没有设置其他任何东西,或者您是否必须像这样设置它use \MyFirstNamespace\Foo as Foo;
    • use \Foo\Bar\MyClassuse \Foo\Bar\MyClass as MyClass 相同。是否要设置别名完全取决于您。在大多数情况下我也不这样做;)
    • 完美,正是我希望听到的!
    【解决方案2】:

    命名空间有很多优点。

    首先你可以重用方法名甚至类名,前提是它们存在于不同的命名空间中。示例:

    namespace \myNamespace\data\postgres;
    
    class DataBase extends \PDO
    {
    }
    
    namespace \myNamespace\data\mysql;
    
    class DataBase extends \PDO
    {
    }
    

    您甚至可以重用通常为 PHP 函数保留的名称

    namespace \myNamespace\dir;
    
    function makedir ()
    {
        if (// some condition is true)
        {
            \makedir ();
        }
    }
    

    所有这些都是为了让不同来源的代码更容易一起使用,而不必担心命名冲突。如果程序员足够有礼貌地遵守一些简单的规则,那么名称冲突的可能性就会大大降低。实际上,为了避免命名冲突,您需要关注的唯一规则就是让您的命名空间的第一级成为您自己的。例如,使用您的公司名称,或将您标识为唯一供应商的其他方式作为命名空间的第一级,一切都应该是好的。

    例如,我在我编写的所有代码中都使用 \gordian 作为根命名空间,因为我可以在该命名空间下调用我喜欢的任何类,而不必担心它们与选择不同根命名空间的人发生冲突。

    您可能会问,PEAR 约定有什么问题?许多项目都遵循它们,包括流行的 Zend 框架。

    答案是名称很快就会变得非常笨拙。例如,Zend 遵循 PEAR 约定,使用一种伪命名空间。集合中的所有类都以 Zend_ 开头,并且每个级别的类层次结构都在名称中增加了一部分。
    泽 结果,您最终会得到像 Zend_Db_Adaptor_Abstract 和 Zend_Dojo_Form_Decorator_TabContainer 这样的类名。

    如果 Zend 更新他们的框架以使用命名空间(我听说 Zend Framework 2.0 正在发生这种情况),那么它们将被替换为 \Zend\Db\Adaptor\Abstract 和 \Zend\Dojo\Form\Decorator\TabContainer反而。那么,你可能会问?答案是您可以使用 Use 关键字将它们别名为更短的名称,正如您已经看到的那样。这意味着您不必一直写出完整的类名,而只需写出您的别名即可。

    use \Zend\Dojo\Forn\Decorator as Dec;
    
    $a = new Dec\TabContainer; // Not easy to do without namespaces!
    

    此外,如果您已经在给定的命名空间中,那么您甚至不必使用 use 关键字通过短名称访问同一命名空间中的其他项目,因为在这种情况下它会自动发生.对于框架编写者来说,这是一个巨大的节省时间。

    例如,您可能会在 Zend Framework 2 中看到类似以下内容(因为我没有以任何方式处理它,这纯粹是一个示例,并非来自实际的 ZF2 源代码)。

    namespace \Zend\Db\Adaptor;
    
    class Postgres extends Abstract // We don't need to use \Zend\Db\Adaptor\Abstract here because it's in the same namespace already anyway
    {
    }
    

    还有其他好处,例如它使自动加载器的制作非常简单(前提是您的命名空间结构完全映射到您的文件系统目录结构)。

    命名空间可能看起来不是很重要的功能之一,甚至似乎没有任何意义,但使用它们一段时间后,它们的用处会突然变得非常明显。

    【讨论】:

      猜你喜欢
      • 2014-02-24
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多