PHP名称空间

PHP的名称空间(namespace)类似于C++的名称空间。名为PHP或者php的名称空间,以及以它们开头的命名空间被保留作语言内核使用。

只有类、抽象类、traits、接口、函数和常量才会受命名空间的影响。命名空间通过关键字namespace来声明。如果一个文件中包含命名空间,它必须是任何别的代码之前声明,这条原则的特例是declare关键字。PHP不支持嵌套名称空间,但是用多个\可以达到一样的效果。

1
2
3
4
namespace MyProject\Network;
const CONNECT_OK = 1;       //MyProject\Network\CONNECT_OK
class Connection { /* … */ }    //MyProject\Network\Connection
function connect() { /* … */ }   //MyProject\Network\connect

命名空间的<?php标签之前不允许出现任何字符,必须是文件的第一个字符串。命名空间可以分割到多个文件中。

可以在同一个文件中定义多个命名空间,推荐用法是用大括号分割。命名空间的括号外不能有任何PHP代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
namespace MyProject\Network {
    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */ }
}
namespace {
    session_start();
    $a = MyProject\Network\connect();
    echo MyProject\Network\Connection::start();
}

引入命名空间后,PHP的类名可以通过三种方式引用:

  • 非限定名称(unqualified name),或不包含任何前缀的类名称。形如:$a = new foo(); 或 foo::staticmethod(); 如果当前命名空间是currentnamespace,foo将被解析为 currentnamespace\foo。如果命名空间中没有定义这个函数或常量,则该非限定的函数名称或常量名称被解析为全局函数或常量,对于类会报致命错误;
  • 限定名称(qualified name),或包含前缀的类名称。形如:$a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod(); 如果当前名称为currentnamespace,foo将被解析为currentnamespace\subnamespace\foo。如果在全局环境中,foo江北解析为subnamespace\foo;
  • 完全限定名称(full qualified name),或包含\全局前缀操作符的名称,如:$a = new \currentnamespace\foo();或\currentnamespace\foo::staticmethod(); 。这种情况下foo就是currentnamespace\foo;

访问任意全局类、函数或常量,都可以使用完全限定名称,例如\strlen()或\Exception或\INI_ALL。在变量中存储包含名称空间的类名、函数名、常量名时必须用完全限定名称,并且没有前导\和有是一样的效果,都是完全限定。

在访问当前名称空间内部元素时,NAMESPACE和namespace关键字是一样的。常量NAMESPACE的值包含当前命名空间名称字符串,在全局环境中则为空串。namespace关键字相当于类中的self操作符。__NAMESPACE__\funcnamespace\func是一样的。NAMESPACE 通常用来创建动态名称,如:

1
2
3
4
function get($classname) {
    $a = __NAMESPACE__ . "\\" . $classname;
    return new $a();
}

PHP允许用use as来导入类、接口、命名空间,给它们取别名。PHP5.6开始允许导入函数或常量。use中的名称空间必须是完全限定的,而且不需要前导\。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
namespace foo;
use My\Full\Classname as Another;
// 下面的例子与 use My\Full\NSname as NSname 相同
use My\Full\NSname;
// 导入一个全局类
use ArrayObject;
// 导入function/constant (PHP 5.6+)
use function My\Full\functionName;
use function My\Full\functionName as func;
use const My\Full\CONSTANT;

导入操作是在编译期执行的,动态类名、函数名或者常量名是在运行时得到的。因而动态类名不会受到导入的影响,还是必须使用完全限定名。还有由于导入操作是在编译期执行的,所有use必须在全局环境或者namespace声明中,不能在任何类、函数等块域中。

1
2
3
4
use My\Full\Classname as Another;
$obj = new Another; // 实例化一个 My\Full\Classname 对象
$a = 'Another';
$obj = new $a;      // 实际化一个 Another 对象

不推荐在一行中包含多个use语句。use不具有传递性,因而被require的文件不能继承父文件中的别名。

对于没有在任何名称中间中的函数、类就在全局名称空间中,在名称前加上前缀\表示该名称在全局空间中,如:$f = \fopen($file);