php中的命名空间这一概念,是在5.3.0版本开始引入的。最主要的目的就是为了解决类、常量等的名字冲突问题。附带的也能够提高一些代码的可读性。
如果实在不好理解,那就把命名空间当做一个文件系统中的目录声明,就如同文件系统目录一样,同一目录下不会存在两个相同名字的文件,但不同目录下的文件可以名字相同。
包括类、接口、函数和常量这些类型的代码会受到命名空间的影响。
声明
命名空间使用关键字“namespace”来声明。必须处于代码的最前列,即如下这种形式:
<?php
namespace workspace;
只有一种情况例外,那就是定义编码方式的“declare”关键字可以位于命名空间之前声明。
<?php
declare(encoding='ISO-8859-1');
namespace workspace;
除了以上说明的这两种情况,其它的声明方式都属于非法。
子命名空间
如同文件目录包含子目录一样,命名空间也支持子命名空间,例如:
<?php
namespace workspace\php\think;
class Coo{}
这样就创建了workspace\php\think\Coo这个类。
虽然php也支持在同一个文件中定义多个命名空间,但非常不推荐这样做!
三种使用方式
我们在使用文件系统的时候,知道有3种定位文件的方式,分别是:同级文件(相同目录下)、相对路径(所处目录的子目录下或父目录下)、绝对路径(给定的完整路径)。
而同样的,在命名空间中也支持3种方式引用:
非限定方式(无前缀)(类似目录中的同级文件方式)
<?php
namespace workspace;
$a = new Coo(); // 会被解析为workspace\Coo
限定方式(有前缀)(类似目录中的相对路径方式)
<?php
namespace workspace;
$a = new myphp\Coo(); // 会被解析为workspace\myphp\Coo
完全限定方式(绝对指定)(类似目录中的绝对路径方式)
<?php
namespace workspace;
$a = new \mythink\Coo(); // 会被解析为mythink\Coo
全局、局部声明引用
当你的命名空间中声明了与全局函数名称相同的函数名时,如以下这种情况:
<?php
namespace workspace;
function strlen(){}
$a = strlen(); // 调用的是上面声明的strlen函数
$b = \strlen('hello'); // 调用的是php全局函数strlen
var_dump($a); // 输出为NULL
var_dump($b); // 输出为int(5)
动态引用
需要注意,如果是动态访问,那限定方式和完全限定方式是没有区别的。例如:
<?php
namespace workspace;
function foo(){}
$a = 'foo';
$a(); // 会发生错误
$b = 'myzz\foo';
$b(); // 调用的是myzz\foo,而不是workspace\myzz\foo
$c = '\myzz\foo';
$c(); // 调用的是myzz\foo
$d = 'workspace\foo';
$d(); // 调用的是workspace\foo,而不是workspace\workspace\foo
常量
__NAMESPACE__
常量,包含了当前命名空间的名称。如果未定义命名空间,则使用此常量会输出一个空字符串。
<?php
namespace workspace;
echo __NAMESPACE__; //输出为workspace
<?php
echo __NAMESPACE__; //输出为空字符串""
别名与引用
命名空间也可以使用别名,在整个命名空间很长的时候,就可以定义一个简单的别名方便以后使用。
<?php
namespace workspace;
use myspace\think\Coo as CCoo;
$a = new CCoo; // myspace\think\Coo
use也可用引用命名空间,类似简写的别名方式:
<?php
namespace workspace;
use myspace\think\Coo; // 与"use myspace\think\Coo as Coo"相同
简单实例
以两个文件,a.php和b.php来进行举例,文件内容分别如下:
a.php内容:
<?php
namespace mybb;
class ppp{}
b.php内容:
<?php
namespace myaa;
include 'a.php';
use mybb\ppp as another;
class ppp{}
$a = new another;
var_dump($a);
$b = new ppp();
var_dump($b);
执行b.php后能够得到输出:
# php b.php
object(mybb\ppp)#1 (0) {
}
object(myaa\ppp)#2 (0) {
}
可以看到,同一个名称的类ppp,在不同的命名空间中就可以同时存在并被正确调用。