一、定义
PHP命名空间名称解析规则是指在PHP中,如何解析和处理命名空间的名称。在PHP 5.3及更高版本中,引入了命名空间的概念,用于解决类名冲突的问题。
在说明名称解析规则之前,我们先看一些重要的定义:
命名空间名称定义:
1、非限定名称(Unqualified name):名称中不包含命名空间分隔符的标识符,例如 Foo;
2、限定名称(Qualified name):名称中含有命名空间分隔符的标识符,例如 Foo\Bar;
3、完全限定名称(Fully qualified name):名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如 \Foo\Bar。 namespace\Foo 也是一个完全限定名称;
4、相对名称(Relative name):这是个以 namespace 开头的标识符, 例如 namespace\Foo\Bar。
二、名称解析遵循规则
1、完全限定名称总是会解析成没有前缀符号的命名空间名称。 \A\B 解析为 A\B。
2、解析相对名称时,会用当前命名空间的名称替换掉 namespace。 如果名称出现在全局命名空间,会截掉 namespace\ 前缀。 例如,在命名空间 X\Y 里的 namespace\A 会被解析成 X\Y\A。 在全局命名空间里,同样的名字却被解析成 A。
3、对于限定名称,名字的第一段会根据当前 class/namespace 导入表进行翻译。 比如命名空间 A\B\C 被导入为 C, 名称 C\D\E 会被翻译成 A\B\C\D\E。
4、对于限定名称,如果没有应用导入规则,就将当前命名空间添加为名称的前缀。 例如,位于命名空间 A\B 内的名称 C\D\E 会解析成 A\B\C\D\E。
5、根据符号类型和对应的当前导入表,解析非限定名称。 这也就是说,根据 class/namespace 导入表翻译类名称; 根据函数导入表翻译函数名称; 根据常量导入表翻译常量名称。 比如,在 use A\B\C; 后,类似 new C() 这样的名称会解析为 A\B\C()。 类似的,use function A\B\foo; 后, foo() 的用法,解析名称为 A\B\foo。
6、如果没有应用导入规则,对于类似 class 符号的非限定名称,会添加当前命名空间作为前缀。 比如命名空间 A\B 内的 new C() 会把名称解析为 A\B\C。
7、如果没有应用导入规则,非限定名称指向函数或常量,且代码位于全局命名空间之外,则会在运行时解析名称。 假设代码位于命名空间 A\B 中, 下面演示了调用函数 foo() 是如何解析的:
- 在当前命名空间中查找函数: A\B\foo();
- 它会尝试找到并调用 全局 的函数 foo()。
三、名称解析示例
<?php namespace A; use B\D, C\E as F; // 函数调用 foo(); // 首先尝试调用定义在命名空间"A"中的函数foo() // 再尝试调用全局函数 "foo" \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" ?>