首頁  >  文章  >  後端開發  >  什麼是php命名空間?命名空間用法實例詳解

什麼是php命名空間?命名空間用法實例詳解

伊谢尔伦
伊谢尔伦原創
2017-06-30 09:23:211204瀏覽

PHP 在 5.3.0 以後的版本開始支援命名空間。什麼是命名空間?從廣義來說,命名空間是一種封裝事物的方法。在很多地方都可以看到這種抽象概念。

命名空間概述

在PHP中,命名空間用來解決在編寫類別庫或應用程式時創建可重複使用的程式碼如類別或函數時碰到的兩類問題:

使用者所寫的程式碼與PHP內部的類別/函數/常數或第三方類別/函數/常數之間的名字衝突。
為很長的識別碼名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高原始碼的可讀性。
PHP 命名空間提供了一種將相關的類別、函數和常數組合在一起的途徑。下面是一個說明PHP 命名空間語法的範例:

定義命名空間

#雖然任意合法的PHP程式碼都可以包含在命名空間中,但只有三種類型的程式碼受命名空間的影響,它們是:類,函數和常數。命名空間透過關鍵字namespace 來聲明。如果一個檔案中包含命名空間,它必須在其它所有程式碼之前聲明命名空間。另外,與PHP其它的語言特徵不同,同一個命名空間可以定義在多個檔案中,即允許將同一個命名空間的內容分割存放在不同的檔案中。當然你也可以在同一個檔案中定義多個命名空間。

namespace MyProject;
class MyClass
{
    #code...
}

定義子命名空間:與目錄和檔案的關係很像,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層的方式定義:

namespace MyProject\helper\http;
class MyClass
{
    #code...
}

在同一個檔案中定義多個命名空間:在同一個檔案中聲明多個命名空間有兩種方式,但在實際在程式設計實踐中,非常不提倡在同一個檔案中定義多戈命名空間。這種方式的主要用於將多個 PHP 腳本合併在同一個檔案中。下面列出第一種方法。

namespace MyProject\helper\http;
class MyClass
{
    #code...
}
namespace MyProject\helper\request;
class MyClass
{
    #code...
}

不過強烈不建議使用這種方法,可以參考下面的大括號定義法:

namespace MyProject\helper\http;
{
    class MyClass
    {
        #code...
    }
}
namespace MyProject\helper\request;
{
    class MyClass
    {
        #code...
    }
}

PHP 命名空間中的元素使用

在討論如何使用命名空間之前,必須了解PHP 是如何知道要使用哪一個命名空間中的元素的。類別名稱可以透過三種方式引用:

非限定名稱,或不包含前綴的類別名稱,例如 $a=new foo(); 或 foo::staticmethod();。如果目前命名空間是 currentnamespace,foo 將解析為 currentnamespace\foo。如果使用 foo 的程式碼是全域的,不包含在任何命名空間中的程式碼,則 foo 會被解析為foo。 警告:如果命名空間中的函數或常數未定義,則該非限定的函數名稱或常數名稱會被解析為全域函數名稱或常數名稱。詳情請參閱 使用命名空間:後備全域函數名稱/常數名稱。

限定名稱,或包含前綴的名稱,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果目前的命名空間是 currentnamespace,則 foo 會被解析為 currentnamespace\subnamespace\foo。如果使用 foo 的程式碼是全域性的,不包含在任何命名空間中的程式碼,foo 會被解析為subnamespace\foo。

完全限定名稱,或包含了全域前綴運算子的名稱,例如, $a = new \currentnamespace\foo(); 或\currentnamespace\foo::staticmethod(); 。在這種情況下,foo 總是被解析為程式碼中的文字名稱(literal name)currentnamespace\foo。
使用命名空間:別名/導入

允許透過別名引用或匯入外部的完全限定名稱,是命名空間的一個重要特徵。 PHP 命名空間支援 有兩種使用別名或匯入方式:為類別名稱使用別名,或為命名空間名稱使用別名。在PHP中,別名是透過運算子 use 來實現的。

注意PHP不支援導入函數或常數。

namespace foo;
use My\Full\Classname as Another;
// 下面的例子与 use My\Full\NSname as NSname 相同
use My\Full\NSname;
// 导入一个全局类
use \ArrayObject;

名稱解析規則

在說明名稱解析規則之前,我們先看一些重要的定義:

非限定名稱Unqualified name:名稱中不包含命名空間分隔符的標識符,例如Foo
限定名稱Qualified name:名稱中含有命名空間分隔符的標識符,例如Foo\Bar
完全限定名稱Fully qualified name:名稱中包含命名空間分隔符,並以命名空間分隔符開始的標識符,例如\Foo\Bar。 namespace\Foo 也是完全限定名稱。
名稱解析遵循下列規則:

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

new D\E()的解析:
在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。
尝试自动装载类 A\B\D\E。

为了引用全局命名空间中的全局类,必须使用完全限定名称 new \C()。

Example 名称解析示例

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


以上是什麼是php命名空間?命名空間用法實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn