究竟什么是"命名空间"呢? 看看中文手册是怎么说的:
命名空间概述
什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。
例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。
具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中
不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以
及目录分隔符放在文件名之前得到 /home/greg/foo.txt。
这个原理应用到程序设计领域就是命名空间的概念。
在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:
1) 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2) 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
看完概述之后有了初步的概念,用生活中例子描述:
甲有一台iphone5,乙也有一个iphone5,但我们能区分清楚,因为他们分别属于两个不同的人。
命名空间的定义和规则就不多说了,可以看手册介绍。
看看代码是怎么操作的:
创建三个文件分别是file1.ph、file2.php、file3.php、file4.php 他们同属于一个目录级里面。
1) file1.php
<?php
//这是其中一种定义命名空间的方式
namespace App\Lib1;
const MYCONST = 'App\Lib1\MYCONST';
function MyFunction() {
return __FUNCTION__;
}
class MyClass
{
static function WhoAmI() {
return __METHOD__;
}
}
?>
2) file2.php
<?php
//这是另外一种使用代码块的方式定义命名空间,这方式可以区分开同一个文件里两个不同的命名空间的定义(但是不建议做)。
namespace App\Lib2
{
const MYCONST = 'App\Lib2\MYCONST';
function MyFunction() {
return __FUNCTION__;
}
class MyClass
{
static function WhoAmI() {
return __METHOD__;
}
}
}
?>
file4.php
<?php
//普通的PHP文件,并未定义命名空间
const MYCONST = 'App\Lib4\MYCONST';
function MyFunction() {
return __FUNCTION__;
}
class MyClass
{
static function WhoAmI() {
return __METHOD__;
}
}
?>
到这里file1.php和file2.php内容几乎一样, 只有命名空间的名字不同。
另外还要补充一下关于命名空间的一些相关术语:
完全限定名称(Fully-qualified name):
任何PHP代码都可以引用完全限定名称,它是一个以命名空间反斜线开头的标识符,如\App\Lib1\MYCONST,\App\Lib2\MyFunction( )等。
完全限定名称是没有任何歧义的,开头的反斜线和文件路径的作用有点类似,它表示“根”全局空间,如果我们在全局空间中实现了一个不同的MyFunction( ),可以使用\MyFunction( )从lib1.php或lib2.php调用它。
完全限定名称对一次性函数调用或对象初始化非常有用,但当你产生了大量的调用时它们就没有实用价值了,在下面的讨论中我们将会看到,PHP提供了其它选项以解除我们为命名空间打字的烦恼。
限定名称(Qualified name):
至少有一个命名空间分隔符的标识符,如Lib1\MyFunction( )。
非限定名称(Unqualified name):
没有命名空间分隔符的标识符,如MyFunction( )。
看看file3.php是如何使用的命名空间
<?php
/**
* 若当前PHP文件没有定义命名空间,当require_once('file4.php')时就会发生冲突
* Fatal error: Cannot redeclare MyFunction()
*/
namespace App\Lib3;
/* 这里下面是file3.php命名空间的一些定义 */
const MYCONST = 'App\Lib3\MYCONST';
function MyFunction() {
return __FUNCTION__;
}
class MyClass
{
static function WhoAmI() {
return __METHOD__;
}
}
/**
* 把file1.php、file2.php、file4.php包含进来file3.php之后,尝试输出 echo MYCONST; 结果会是App\Lib3\MYCONST,
* 为什么不是file4.php里面定义的MYCONST常量呢?因为file4.php是属于"根"的全局空间,并且输出时没有指定使用哪个命名
* 空间(非限定名称),所以默认是当前文件的MYCONST常量,若要输出file4.php的常量,可以这样 echo \MYCONST;
*/
require_once('file1.php');
require_once('file2.php');
require_once('file4.php');
/**
* 光是把定义了命名空间的文件包含进来,还不能使用各自的定义,需要使用 use 操作符导入命名空间
* 格式: use 命名空间; ,另外对于很长的命名空间定义还能够使用别名,类似SQL的as, 格式: use 命名空间 as 别名;
*/
use App\Lib1;
use App\Lib2 as B;
/* 开始享受命名空间带来的便利了 */
#完全限定名称
#类似于绝对路劲,从“根”开始.
echo \App\Lib1\MYCONST . "<br/>";
echo \App\Lib1\MyFunction() . "<br/>";
echo \App\Lib1\MyClass::WhoAmI() . "<br/>";
#限定名称
#类似于相对路劲,让系统自己去搜索.
echo B\MYCONST . "<br/>";
echo B\MyFunction() . "<br/>";
echo B\MyClass::WhoAmI() . "<br/>";
#非限定名称
echo MYCONST . "<br/>";
echo MyFunction() . "<br/>";
echo MyClass::WhoAmI() . "<br/>";
?>
到这里已经对命名空间有一定的认识,下面再看看一些高级应用:
__NAMESPACE__常量
__NAMESPACE__是一个PHP字符串,它总是返回当前命名空间的名称,在全局空间(file4.php就是属于全局空间)中它是一个空字符串。
< ?php
namespace App\Lib1;
echo __NAMESPACE__; // outputs: App\Lib1
?>
这个值在调试时非常有用,它也可由于动态生成一个完全限定类名,如:
< ?php
namespace App\Lib1;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
$c = __NAMESPACE__ . '\\MyClass';
$m = new $c;
echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
?>
namespace关键字
namespace关键字可以用于明确引用一个当前命名空间或子命名空间中的项目,它等价于类中的self命名空间:
更多详细的介绍在手册里面,非常多例子。
< ?php
namespace App\Lib1;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
$m = new namespace\MyClass;
echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI
?>
自动载入命名空间类
PHP 5中最省时省力的特性是自动载入,在全局(非命名空间)PHP代码中,可以写一个标准自动载入函数:
< ?php
$obj= new MyClass1(); // classes/MyClass1.php is auto-loaded
$obj= new MyClass2(); // classes/MyClass2.php is auto-loaded
// autoload function
function __autoload($class_name) {
require_once("classes/$class_name.php");
}
?>
在PHP 5.3中,你可以创建一个命名空间类的实例,在这种情况下,完全限定命名空间和类名传递给__autoload函数,例如,$class_name的值可 能是App\Lib1\MyClass。你可以在相同的文件夹下放置所有的PHP类文件,从字符串中提取命名空间,但那样会导致文件名冲突。
另外,你的类文件层次结构会按照命名空间的结构重新组织,例如,MyClass.php文件可以创建在/classes/App/Lib1文件夹下:
/classes/App/Lib1/MyClass.php
< ?php
namespace App\Lib1;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
?>
在根文件夹下的文件就使用下面的代码了:
myapp.php
< ?php
use App\Lib1\MyClass as MC;
$obj = new MC();
echo $obj->WhoAmI();
// autoload function
function __autoload($class) {
// convert namespace to full file path
$class = 'classes/' . str_replace('\\', '/', $class) . '.php';
require_once($class);
}
?>
解释:
1.类App\Lib1\MyClass的别名是MC;
2. new MC( )在编译时被翻译成new App\Lib1\MyClass( );
3.字符串App\Lib1\MyClass被传递给__autoload函数,使用文件路径正斜线替换所有命名空间中的反斜线,然后修改字符串,classes\App\Lib1\MyClass.php文件被自动载入;
本文努力转自http://my.oschina.net/Jacker/blog/32943