资讯专栏INFORMATION COLUMN

【转】php命名空间

Jrain / 3044人阅读

摘要:命名空间可以解决以下两类问题用户编写的代码与内部的类函数常量或第三方类函数常量之间的名字冲突。在命名空间内部访问全局类函数和常量调用全局函数访问全局常量实例化全局类命名空间和动态语言特征命名空间的实现受到其语言自身的动态特征的影响。

PHP 命名空间(namespace)是在PHP 5.3中加入的,如果你学过C#和Java,那命名空间就不算什么新事物。 不过在PHP当中还是有着相当重要的意义。

PHP 命名空间可以解决以下两类问题:

用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。

为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。


定义命名空间

默认情况下,所有常量、类和函数名都放在全局空间下,就和PHP支持命名空间之前一样。

命名空间通过关键字namespace 来声明。如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。语法格式如下;

< ?php  
// 定义代码在 "MyProject" 命名空间中  
namespace MyProject;  
 
// ... 代码 ...  
?>

你也可以在同一个文件中定义不同的命名空间代码,如:

< ?php  
namespace MyProject1;  
// MyProject1 命名空间中的PHP代码  
 
namespace MyProject2;  
// MyProject2 命名空间中的PHP代码    
 
// 另一种语法
namespace MyProject3 {  
 // MyProject3 命名空间中的PHP代码    
}  
?>  

在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。

以下代码会出现语法错误:


” 会致命错误 - 命名空间必须是程序脚本的第一条语句
?>
子命名空间

与目录和文件的关系很象,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义:

上面的例子创建了常量 MyProjectSubLevelCONNECT_OK,类 MyProjectSubLevelConnection 和函数 MyProjectSubLevelConnect。

命名空间使用

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

非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespacefoo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。

限定名称,或包含前缀的名称,例如 $a = new subnamespacefoo(); 或 subnamespacefoo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespacesubnamespacefoo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespacefoo。

完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new currentnamespacefoo(); 或 currentnamespacefoo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespacefoo。
下面是一个使用这三种方式的实例:

file1.php 文件代码

file2.php 文件代码

注意访问任意全局类、函数或常量,都可以使用完全限定名称,例如 strlen() 或 Exception 或 INI_ALL。

在命名空间内部访问全局类、函数和常量:

命名空间和动态语言特征

PHP 命名空间的实现受到其语言自身的动态特征的影响。因此,如果要将下面的代码转换到命名空间中,动态访问元素。

example1.php 文件代码:

必须使用完全限定名称(包括命名空间前缀的类名称)。注意因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。

动态访问命名空间的元素

namespace关键字和__NAMESPACE__常量

PHP支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和namespace关键字。

常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。

NAMESPACE 示例, 在命名空间中的代码

NAMESPACE 示例,全局代码

常量 NAMESPACE 在动态创建名称时很有用,例如:

使用__NAMESPACE__动态创建名称

关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。

amespace操作符,命名空间中的代码

namespace操作符, 全局代码

使用命名空间:别名/导入

PHP 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。注意PHP不支持导入函数或常量。

在PHP中,别名是通过操作符 use 来实现的. 下面是一个使用所有可能的三种导入方式的例子:

1、使用use操作符导入/使用别名

2、 一行中包含多个use语句

导入操作是在编译执行的,但动态的类名称、函数名称或常量名称则不是。

3、导入和动态名称

另外,导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响。
4、导入和完全限定名称

使用命名空间:后备全局函数/常量

在一个命名空间中,当 PHP 遇到一个非限定的类、函数或常量名称时,它使用不同的优先策略来解析该名称。类名称总是解析到当前命名空间中的名称。因此在访问系统内部或不包含在命名空间中的类名称时,必须使用完全限定名称,例如:

1、在命名空间中访问全局类

对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量。

2、 命名空间中后备的全局函数/常量

全局空间

如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀 表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。

使用全局空间说明

命名空间的顺序

自从有了命名空间之后,最容易出错的该是使用类的时候,这个类的寻找路径是什么样的了。

名称解析遵循下列规则

对完全限定名称的函数,类和常量的调用在编译时解析。例如 new AB 解析为类 AB。

所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 ABC 被导入为 C,那么对 CDe() 的调用就会被转换为 ABCDe()。

在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 AB 内部调用CDe(),则 CDe() 会被转换为 ABCDe() 。

非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 ABC 导入为C,则 new C() 被转换为 new ABC() 。

在命名空间内部(例如AB),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:

在当前命名空间中查找名为 ABfoo() 的函数

尝试查找并调用 全局(global) 空间中的函数 foo()。

在命名空间(例如AB)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用 new C() 及 new DE() 的解析过程: new C()的解析:

在当前命名空间中查找ABC类。

尝试自动装载类ABC。

new DE()的解析:

在类名称前面加上当前命名空间名称变成:ABDE,然后查找该类。

尝试自动装载类 ABDE。

为了引用全局命名空间中的全局类,必须使用完全限定名称 new C()。
http://www.manongjc.com/php/p...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22944.html

相关文章

  • PHP-PSR 现代PHPer的开发规范

    摘要:的使命是实现框架之间的互操作性。个人和官方都认为开发者应该遵循更为严格的代码标准,在现代的生态系统中,风格统一,可以更好的让其他开发者理解代码。记录的消息用于诊断检查和排除应用中的操作稳定性和性能方面的问题。 原文是在我自己博客中,小伙伴也可以点阅读原文进行跳转查看,还有好听的背景音乐噢~     PSR是PHP Standards Recommendation的简称,意为PHP推荐标...

    zebrayoung 评论0 收藏0
  • Composer的Autoload源码实现——启动与初始化

    摘要:任务是加载类的初始化顶级命名空间与文件路径映射初始化和注册。在实际情况下可能会出现这样的情况。值得注意的是这个函数返回的是一个匿名函数,为什么呢原因就是类中的等等都是的。。。关于匿名函数的绑定功能。 前言 在开始之前,欢迎关注我自己的博客:www.leoyang90.cn 上一篇文章,我们讨论了 PHP 的自动加载原理、PHP 的命名空间、PHP 的 PSR0 与 PSR4 标准,有...

    MarvinZhang 评论0 收藏0
  • Composer的Autoload源码实现——注册与运行

    前言 在开始之前,欢迎关注我自己的博客:www.leoyang90.cn上一篇 文章我们讲到了 Composer 自动加载功能的启动与初始化,经过启动与初始化,自动加载核心类对象已经获得了顶级命名空间与相应目录的映射,换句话说,如果有命名空间 AppConsoleKernel,我们已经知道了 App 对应的目录,接下来我们就要解决下面的就是 ConsoleKernel这一段。 注册 我们先回顾...

    wanghui 评论0 收藏0
  • PHP面试常考内容之面向对象(3)

    摘要:面试专栏正式起更,每周一三五更新,提供最好最优质的面试内容。继上一篇面试常考内容之面向对象发表后,今天更新面向对象的最后一篇。面向对象的主要特征为封装继承多态。为了提高内聚性减少引起变化,单一原则是低耦合高内聚的面向原则上的引申。 PHP面试专栏正式起更,每周一、三、五更新,提供最好最优质的PHP面试内容。继上一篇PHP面试常考内容之面向对象(2)发表后,今天更新面向对象的最后一篇(3...

    xfee 评论0 收藏0
  • 【日常手记】之Laravel5.3

    摘要:个人网站最近刚写了一个手机在线播放的电影站使用日常手记更新使用的的查询作用域的本地作用域去自定义可复用的约束集合,方便链式调用什么是本地查询作用域本地作用域允许我们定义通用的约束集合以便在应用中复用。 关于作者 程序开发人员,不拘泥于语言与技术,目前主要从事PHP和前端开发,使用Laravel和VueJs,App端使用Apicloud混合式开发。合适和够用是最完美的追求。 个人网站:...

    kidsamong 评论0 收藏0

发表评论

0条评论

Jrain

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<