本文主要参考《Modern PHP》一书,文章链接
命名空间
在PHP5.3.0中引入,是一个很重要的工具,其作用是按照一种虚拟的层次结构组织PHP代码,这种层次结构类似操作系统中文件系统的目录结构。现代的PHP组件框架代码都是放在各自全局唯一的厂商命名空间中,以免和其他厂商使用的常见类名冲突。
命名空间很重要,因为代码放在沙盒中,可以和其他开发者编写的代码一起使用。这是现代PHP组件生态系统的基础
。
我们的代码可能和其他开发者的代码使用相同的类名、接口名、函数或常量名,如果不使用命名空间,名称会起冲突,导致PHP执行出错。而使用命名空间将代码放到唯一的厂商命名空间,我们的代码就可以和其他开发者使用相同的类名、接口名、函数或常量名。
每个PHP类、接口、函数和常量都在命名空间(子命名空间)中。在
namespace Oreilly;
在命名空间出现之前,PHP开发者使用Zend风格的类名解决命名冲突问题,这是一种类的命名方案,因Zend框架而流行,这种命名方案在PHP类名中使用下划线的方式表示文件系统的目录分隔符。这种约定有两个作用:其一,确保类名是唯一的;其二,原生的自动加载器会把类名中的下划线替换成文件系统的目录分隔符,从而确定文件的路径。例如,Zend_Cloud_DocumentService_Adapter_WindowsAzure_Query
类对应的文件是Zend/Cloud/DocumentService/Adapter/WindowsAzure/Query.php
。可以看出,这种命名有个缺点:类名特别长。
导入的意思是指,在每个PHP文件中告诉PHP想使用哪个命名空间、类、接口、函数和常量,导入后就不用使用全名了。
示例1: 使用命名空间,没创建别名
$response = new \Symfony\Component\HttpFoundation\Response('Oops', 400);
$response->send();
示例2: 使用命名空间和默认的别名
use Symfony\Component\HttpFoundation\Response;
$response = new Response('Oops', 400);
$response->send();
示例3: 使用命名空间,并自定义别名
use Symfony\Component\HttpFoundation\Response as Res;
$r = new Res('Oops', 400);
$r->send();
从PHP 5.6开始还可以导入函数和常量,不过要调整use关键字的句法,如果要导入函数,需要使用use func
:
use func Namespace\functionName
functionName();
如果想导入常量,可以使用use constant
:
use constant Namespace\CONST_NAME;
echo CONST_NAME;
use Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpFoundation\Response,
Symfony\Component\HttpFoundation\Cookie;
但是为了可读性,建议不要这么写,还是一行写一个use语句比较好:
use Symfony\Component\HttpFoundation\Request,
use Symfony\Component\HttpFoundation\Response,
use Symfony\Component\HttpFoundation\Cookie;
PHP允许在一个PHP文件中定义多个命名空间,如下示例:
namespace Foo {
//声明类、接口、函数、常量
}
namespace Bar {
//声明类、接口、函数、常量
}
如果引用的类、接口、函数和常量没有指定命名空间,PHP假定引用的类、接口、函数和常量在当前的命名空间中。如果这个假定不正确,PHP会尝试解析类、接口、函数或常量。如果需要在命名空间中引用其他命名空间的类、接口、函数或常量,需要使用完全限定的PHP类名(命名空间+类名
)。
示例:在命名空间中使用非限定的类名
namespace My\App;
class Foo {
public function doSomething() {
throw new Exception();//报错,因为PHP会搜索\My\App\Exception, 而这个类不存在
}
}
因此,我们要在Exception类的名称前加上\
前缀,如下示例所示。这么做的目的是告诉PHP别在当前命名空间中查找Exception类,要在全局命名空间中查找。
namespace My\App;
class Foo {
public function doSomething() {
throw new \Exception();
}
}
命名空间还为 PHP-FIG 制定的 PSR-4 自动加载标准奠定了坚实的基础,大多数现代的 PHP 组件都使用了这种自动加载模式,使用依赖管理器 Composer 可以自动加载项目的依赖。现在你只需要知道没有命名空间,就没有现代的 PHP 生态系统和基于组件的新型架构,由此可见命名空间的重要性。