注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

phperwuhan的博客

记载一个phper的历程!phperwuhan.blog.163.com

 
 
 

日志

 
 

php5.3"命名空间"详解  

2014-03-21 19:58:04|  分类: php |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
来源:http://my.oschina.net/Jacker/blog/32943

究竟什么是"命名空间"呢? 看看中文手册是怎么说的:

命名空间概述

什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。

例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。

具体举个例子,文件 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

01<?php
02//这是其中一种定义命名空间的方式
03namespace App\Lib1;
04 
05const MYCONST = 'App\Lib1\MYCONST'
06 
07function MyFunction() { 
08    return __FUNCTION__
09
10 
11class MyClass
12{
13    static function WhoAmI() { 
14    return __METHOD__
15    
16}
17?>
 2) file2.php
01<?php
02//这是另外一种使用代码块的方式定义命名空间,这方式可以区分开同一个文件里两个不同的命名空间的定义(但是不建议做)。
03namespace App\Lib2
04{
05    const MYCONST = 'App\Lib2\MYCONST'
06 
07    function MyFunction() { 
08        return __FUNCTION__
09    
10 
11    class MyClass
12    {
13        static function WhoAmI() { 
14            return __METHOD__;
15        
16    }
17}
18?>

file4.php

01<?php
02//普通的PHP文件,并未定义命名空间
03const MYCONST = 'App\Lib4\MYCONST'
04 
05function MyFunction() { 
06    return __FUNCTION__
07
08 
09class MyClass
10{
11    static function WhoAmI() { 
12        return __METHOD__;
13    
14}
15?>


到这里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是如何使用的命名空间

01<?php
02/**
03 * 若当前PHP文件没有定义命名空间,当require_once('file4.php')时就会发生冲突
04 * Fatal error: Cannot redeclare MyFunction()
05 */
06namespace App\Lib3;
07 
08/* 这里下面是file3.php命名空间的一些定义 */
09const MYCONST = 'App\Lib3\MYCONST';
10 
11function MyFunction() {
12    return __FUNCTION__;
13}
14 
15class MyClass
16{
17    static function WhoAmI() { 
18        return __METHOD__;
19    }
20}
21 
22/**
23 * 把file1.php、file2.php、file4.php包含进来file3.php之后,尝试输出 echo MYCONST; 结果会是App\Lib3\MYCONST,
24 * 为什么不是file4.php里面定义的MYCONST常量呢?因为file4.php是属于"根"的全局空间,并且输出时没有指定使用哪个命名
25 * 空间(非限定名称),所以默认是当前文件的MYCONST常量,若要输出file4.php的常量,可以这样 echo \MYCONST;
26 */
27require_once('file1.php');
28require_once('file2.php');
29require_once('file4.php');
30 
31/**
32 * 光是把定义了命名空间的文件包含进来,还不能使用各自的定义,需要使用 use 操作符导入命名空间
33 * 格式: use 命名空间; ,另外对于很长的命名空间定义还能够使用别名,类似SQL的as, 格式: use 命名空间 as 别名;
34 */
35use App\Lib1;
36use App\Lib2 as B;
37 
38/* 开始享受命名空间带来的便利了 */
39#完全限定名称
40#类似于绝对路劲,从“根”开始.
41echo \App\Lib1\MYCONST . "<br/>";
42echo \App\Lib1\MyFunction() . "<br/>";
43echo \App\Lib1\MyClass::WhoAmI() . "<br/>";
44 
45#限定名称
46#类似于相对路劲,让系统自己去搜索.
47echo B\MYCONST . "<br/>";
48echo B\MyFunction() . "<br/>"
49echo B\MyClass::WhoAmI() . "<br/>";
50 
51#非限定名称
52echo MYCONST . "<br/>";
53echo MyFunction() . "<br/>"
54echo MyClass::WhoAmI() . "<br/>";
55?>

到这里已经对命名空间有一定的认识,下面再看看一些高级应用:

__NAMESPACE__常量

__NAMESPACE__是一个PHP字符串,它总是返回当前命名空间的名称,在全局空间(file4.php就是属于全局空间)中它是一个空字符串。

1< ?php 
2namespace App\Lib1; 
3echo __NAMESPACE__; // outputs: App\Lib1 
4?>

这个值在调试时非常有用,它也可由于动态生成一个完全限定类名,如: 

01< ?php 
02namespace App\Lib1; 
03  
04class MyClass { 
05    public function WhoAmI() { 
06        return __METHOD__
07    
08
09 
10$c = __NAMESPACE__ . '\\MyClass'
11$m = new $c
12echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI 
13?>

 

namespace关键字

namespace关键字可以用于明确引用一个当前命名空间或子命名空间中的项目,它等价于类中的self命名空间:

更多详细的介绍在手册里面,非常多例子。

01< ?php 
02namespace App\Lib1; 
03  
04class MyClass { 
05    public function WhoAmI() { 
06        return __METHOD__
07    
08
09  
10$m = new namespace\MyClass; 
11echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI 
12?>

 

自动载入命名空间类

PHP 5中最省时省力的特性是自动载入,在全局(非命名空间)PHP代码中,可以写一个标准自动载入函数:

1< ?php 
2$obj= new MyClass1(); // classes/MyClass1.php is auto-loaded 
3$obj= new MyClass2(); // classes/MyClass2.php is auto-loaded 
4  
5// autoload function 
6function __autoload($class_name) { 
7    require_once("classes/$class_name.php"); 
8
9?>

在PHP 5.3中,你可以创建一个命名空间类的实例,在这种情况下,完全限定命名空间和类名传递给__autoload函数,例如,$class_name的值可 能是App\Lib1\MyClass。你可以在相同的文件夹下放置所有的PHP类文件,从字符串中提取命名空间,但那样会导致文件名冲突。

另外,你的类文件层次结构会按照命名空间的结构重新组织,例如,MyClass.php文件可以创建在/classes/App/Lib1文件夹下:

/classes/App/Lib1/MyClass.php

1<span style="line-height:18px;font-size:12px;">< ?php</span> namespace App\Lib1; 
2  
3class MyClass { 
4    public function WhoAmI() { 
5        return __METHOD__
6    
7
8?>

在根文件夹下的文件就使用下面的代码了:

myapp.php

01<span style="line-height:26px;font-size:12px;-webkit-text-size-adjust:none;">< ?php</span> use App\Lib1\MyClass as MC; 
02  
03$obj = new MC(); 
04echo $obj->WhoAmI(); 
05  
06// autoload function 
07function __autoload($class) { 
08 // convert namespace to full file path 
09 $class = 'classes/' . str_replace('\\', '/', $class) . '.php'
10 require_once($class); 
11
12?>

解释:

1.类App\Lib1\MyClass的别名是MC;

2. new MC( )在编译时被翻译成new App\Lib1\MyClass( );

3.字符串App\Lib1\MyClass被传递给__autoload函数,使用文件路径正斜线替换所有命名空间中的反斜线,然后修改字符串,classes\App\Lib1\MyClass.php文件被自动载入;

  评论这张
 
阅读(348)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017