php命名空间

来源:互联网 发布:h3c s7506e 端口聚合 编辑:程序博客网 时间:2024/06/04 01:34
1、命名空间的意义:
1)用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2)为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名,提高源代码的可读性。
注意:
1)在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的declare 语句。declare(encoding = 'UTF-8');所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。

2、PHP 命名空间中的类名可以通过三种方式引用:
1)非限定名称:$a = new A();如果当前命名空间是 currentnamespace,A将被解析为 currentnamespace\A。如果使用 A的代码是全局的,则 A会被解析为A。
2)限定名称$a = new subnamespace\A(); 如果当前的命名空间是 currentnamespace,则 A会被解析为 currentnamespace\subnamespace\A。如果A是全局的,A会被解析为subnamespace\A。
3)完全限定名称: $a = new \currentnamespace\A();A总是被解析为代码中的文字名currentnamespace\A
3、_NAMESPACE_访问:
<?php
echo'"',__NAMESPACE__,'"';
?>
4、使用命名空间:别名/导入
1)<?phpnamespace foo;
use My\Full\Classname as Another;
use My\Full\NSname as NSname或者use My\Full\NSname;

use \ArrayObject;// 导入一个全局类
$obj = new namespace\Another; // 实例化 foo\Another 对象
$obj = new Another; // 实例化 My\Full\Classname对象
NSname\subns\func(); // 调用函数 My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // 实例化 ArrayObject 对象,如果不使用 "use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象
?>
2)一行中包含多个use语句:<?php
use My\Full\Classname as Another, My\Full\NSname;
?>
3)导入操作只影响非限定名称和限定名称。完全限定名称由于是确定的,故不受导入的影响
$a = 'Another';$obj = new $a;// 实例化一个 Another 对象

5、在命名空间中访问全局类
<?phpnamespace A\B\C;
class Exception extends \Exception {}
$a = new Exception('hi'); // $a 是类 A\B\C\Exception 的一个对象
$b = new \Exception('hi'); // $b 是类 Exception 的一个对象
$c = new ArrayObject; // 致命错误, 找不到 A\B\C\ArrayObject 类
?>
对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量。

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

7、命名空间的顺序
<?phpnamespace A;use B\D, C\E as F;
foo();---->// 首先尝试调用定义在命名空间"A"中的函数foo(),再尝试调用全局函数\foo();     
调用全局空间函数my\foo();  ->// 调用定义在命名空间"A\my"中函数 "foo" 
F();---->// 首先尝试调用定义在命名空间"A"中的函数 "F" ,再尝试调用全局函数 "F"
new B();---->// 创建命名空间 "A" 中定义的类 "B" 的一个对象,如果未找到,则尝试自动装载类 "A\B"
new D();---->// 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象,如果未找到,则尝试自动装载类 "B\D"
new F();---->// 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象,如果未找到,则尝试自动装载类 "C\E"
new \B();---->// 创建定义在全局空间中的类 "B" 的一个对象,如果未发现,则尝试自动装载类 "B"
new \D();---->// 创建定义在全局空间中的类 "D" 的一个对象,如果未发现,则尝试自动装载类 "D"
new \F();---->// 创建定义在全局空间中的类 "F" 的一个对象,如果未发现,则尝试自动装载类 "F"
调用另一个命名空间中的静态方法或命名空间函数B\foo();->// 调用命名空间 "A\B" 中函数 "foo"
B::foo();---->// 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法,如果未找到类 "A\B" ,则尝试自动装载类 "A\B"
D::foo();---->// 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法,如果类 "B\D" 未找到,则尝试自动装载类 "B\D"
\B\foo();---->// 调用命名空间 "B" 中的函数 "foo" 
\B::foo();---->// 调用全局空间中的类 "B" 的 "foo" 方法,如果类 "B" 未找到,则尝试自动装载类 "B"
当前命名空间中的静态方法或函数A\B::foo();->// 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法,如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"
\A\B::foo();---->// 调用命名空间 "A\B" 中定义的类 "B" 的 "foo" 方法,如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
?>

规则:
1)对完全限定名称的函数,类和常量的调用在编译时解析。例如      new \A\B 解析为类 A\B。
2)所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间     A\B\C 被导入为 C,那么对 C\D\e()     的调用就会被转换为 A\B\C\D\e()。
3)在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间     A\B 内部调用 C\D\e(),则 C\D\e()     会被转换为 A\B\C\D\e() 。
4)非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间     A\B\C 导入为C,则 new C()     被转换为 new A\B\C() 。
5)在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数      foo() 的调用是这样解析的:
a在当前命名空间中查找名为 A\B\foo() 的函数
b尝试查找并调用 全局(global) 空间中的函数 foo()。
6)在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用      new C() 及 new D\E() 的解析过程:       new C()的解析: new D\E()的解析:为了引用全局命名空间中的全局类,必须使用完全限定名称 new \C()。
a在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。
b尝试自动装载类 A\B\D\E。
c在当前命名空间中查找A\B\C类。
d尝试自动装载类A\B\C。
0 0