什么是命名空间

从广义上来说命名空间是一种封装事物的方法,在很多地方都可以看到这种抽象概念,例如在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。

命名空间一个最明确的目的就是解决重名问题。PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误。这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀。

例:项目中有两个模块:article和message board,它们各自有一个处理用户留言的类comment。之后我可能要增加对所有用户留言的一些信息统计功能,比如说我想要得到所有留言的数量。这时候调用它们comment提供的方法是很好的做法,但是同时引入各自的comment类显然是不行的,代码会出错,在另一个地方重写一个comment也会降低维护性。那这时只能重构类名,我约定一个命名规则,在类名前面加上模块名,像这样:article_comment、messageBoard_comment。

可以看到,名字变得很长,那就意味着以后使用comment的时候会写上更多的代码。并且,以后如果要对各个模块增加更多的一些整合功能,或者是互相调用,发生重名的时候就需要重构名字。当然在项目开始的时候就注意到这个问题,并规定命名规则就能很好的避免这个问题。另一个解决方法是可以考虑使用命名空间。

解决的问题

  1. 用户编写的代码与PHP内部的类\函数\常量或第三方类\函数\常量之间的名字冲突
  2. 为很长的标识符名称(通常为了缓解第一类问题而定义的)创建一个别名或简短的名称,提高源代码的可读性

定义

命名空间必须通过关键字namepace来声明,如果一个文件夹中包含命名空间,他必须在其他所有代码之前声明命名空间,可以在同一个文件中定义多个命名空间。如果没有定义命名空间,所有的类与函数的定义都是在全局空间,与PHP引入命名空间前概念一样。

两种定义方式

namespace MyProject1;
/*代码内容*/

namespace MyProject2{
    /*代码内容*/
}

实例

定义单个命名空间

<?php
namespace MySpace {
    function test(){
        echo 'MySpace';
    }
    test();
}

namespace MySpace1{
    function test(){
        echo 'MySpace1';
    }
    test();
}
<?php
namespace A;
function time(){
    echo 'my time function A<br/>';
}
\B\time(); //调用B的命名空间

namespace B;
function time(){
    echo 'my time function B<br/>';
}
time(); // 调用B的命名空间

\A\time(); //调用A的命名空间

echo \time(); //调用系统自有的,全局空间中的名称

定义子命名空间

<?php
namespace A\B;
header("content-type:text/html;charset=utf-8");
class MyClass{
    public function __construct()
    {
        echo '空间A\B中的类实例化了<br/>';
    }
}

namespace A;
class MyClass{
    public function __construct()
    {
        echo '空间A中的类实例化了<br/>';
    }
}

$obj = new MyClass(); //非限定名称
$obj = new \A\B\MyClass(); //完全限定名称
$obj = new \A\MyClass(); //限定名称
$obj = new B\MyClass(); //限定名称

__NAMESPACE__常量

常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。简单来说常量__NAMESPACE__输出的就是空字符串。

使用命名空间:别名/导入

允许通过别名引用或导入外部的完全限定名称,是命名空间的的一个重要特征。

支持三种别名或导入方式:为类名称使用别名,为接口使用别名或为命名空间名称使用别名。PHP5.6开始允许导入函数或常量或为它们设置别名。

通过操作符 use 来实现

<?php
namepace foo;
use My\Full\ClassName; //导入
use My\Full\NsName as MyNs; //别名导入
导入多个
use My\Full\ClassName as another, My\Full\NsName;