## 名称解析规则

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

在说明名称解析规则之前，我们先看一些重要的定义：

命名空间名称定义
非限定名称（Unqualified name）

  名称中不包含命名空间分隔符的标识符，例如 `Foo`

限定名称（Qualified name）

  名称中含有命名空间分隔符的标识符，例如 `Foo\Bar`

完全限定名称（Fully qualified name）

  名称中包含命名空间分隔符，并以命名空间分隔符开始的标识符，例如 `\Foo\Bar`。 `namespace\Foo` 也是一个完全限定名称。

相对名称（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()` 是如何解析的：
   1. 在当前命名空间中查找函数： `A\B\foo()`。
   2. 它会尝试找到并调用 全局 的函数 `foo()`。

示例 #1 名称解析示例

    <?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"
    ?>

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open