在說明名稱解析規則之前,我們先看一些重要的定義:
命名空間名稱定義
非限定名稱
名稱中不包含命名空間分隔符的識別符,例如 Foo
名稱中含有命名空間分隔符的標識符,例如 FooBar
完全限定名稱
名稱中包含命名空間分隔符,並以命名空間分隔符開始的標識符,例如 FooBar。 namespaceFoo 也是完全限定名稱。
名稱解析遵循下列規則:
對完全限定名稱的函數,類別和常數的呼叫在編譯時解析。例如 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()的解析:
new DE()的解析:
為了引用全域命名空間中的全域類,必須使用完全限定名稱 new C()。
在類別名稱前面加上目前命名空間名稱變成:ABDE,然後尋找該類別。
嘗試自動裝載類 ABDE。
在目前命名空間中尋找ABC類別。
嘗試自動裝載類ABC。
名稱解析範例
<?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 E(); // 使用导入规则,创建命名空间 "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" ?>