從廣義來說,命名空間是一種封裝事物的方法。在很多地方都可以看到這種抽象概念。例如,在作業系統中目錄用來將相關檔案分組,而對於目錄中的檔案來說,它就扮演了命名空間的角色。這個原理應用在程式設計領域就是命名空間的概念
在PHP中,命名空間用來解決在編寫類別庫或應用程式時創建可重複使用的程式碼如類別或函數時碰到的兩類問題:一類是使用者編寫的程式碼與PHP內部的類別/函數/常數或第三方類別/函數/常數之間的名字衝突;另一類是為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高原始碼的可讀性。 PHP命名空間提供了一種將相關的類別、函數和常數組合在一起的途徑。本文將詳細介紹PHP的命名空間
雖然任意合法的PHP程式碼都可以包含在命名空間中,但只有以下類型的程式碼受命名空間的影響,它們是:類別(包括抽象類別和traits)、介面、函數和常數
命名空間透過關鍵字namespace來聲明。如果一個檔案包含命名空間,它必須在其它所有程式碼之前聲明命名空間,除了一個以外:declare關鍵字
<?<span style="color: #000000;">php namespace MyProject; </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span>?>
子命名空間
與目錄和檔案的關係很像,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層的方式來定義
<?<span style="color: #000000;">php namespace MyProject\Sub\Level; </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span>?>
<?<span style="color: #000000;">php namespace MyProject\Sub\Level; </span><span style="color: #0000ff;">const</span> NUM = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">echo</span> NUM;<span style="color: #008000;">//</span><span style="color: #008000;">1</span> <span style="color: #0000ff;">echo</span> \MyProject\Sub\Level\NUM;<span style="color: #008000;">//</span><span style="color: #008000;">1</span> ?>
可以在同一個檔案中定義多個命名空間。在同一個檔案中定義多個命名空間有兩種語法形式
在實際的程式設計實踐中,非常不提倡在同一個檔案中定義多個命名空間。這種方式的主要用於將多個 PHP 腳本合併在同一個檔案中
【1】簡單組合文法(不建議使用)
<?<span style="color: #000000;">php namespace MyProject; </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } namespace AnotherProject; </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span>?>
【2】大括號文法
<?<span style="color: #000000;">php namespace MyProject { </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } } namespace AnotherProject { </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } } </span>?>
<?<span style="color: #000000;">php namespace MyProject { </span><span style="color: #0000ff;">const</span> NUM = 1<span style="color: #000000;">; } namespace AnotherProject { </span><span style="color: #0000ff;">const</span> NUM = 2<span style="color: #000000;">; </span><span style="color: #0000ff;">echo</span> NUM;<span style="color: #008000;">//</span><span style="color: #008000;">2</span> <span style="color: #0000ff;">echo</span> \MyProject\NUM;<span style="color: #008000;">//</span><span style="color: #008000;">1</span> <span style="color: #000000;">} </span>?>
全域
將全域的非命名空間中的程式碼與命名空間中的程式碼組合在一起,只能使用大括號形式的語法。全域程式碼必須用一個不含名稱的 namespace 語句加上大括號括起來
<?<span style="color: #000000;">php namespace MyProject { </span><span style="color: #0000ff;">const</span> CONNECT_OK = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">class</span> Connection { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } </span><span style="color: #0000ff;">function</span> connect() { <span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span><span style="color: #000000;"> } } namespace { </span><span style="color: #008000;">//</span><span style="color: #008000;"> global code</span> <span style="color: #008080;">session_start</span><span style="color: #000000;">(); </span><span style="color: #800080;">$a</span> =<span style="color: #000000;"> MyProject\connect(); </span><span style="color: #0000ff;">echo</span> MyProject\Connection::<span style="color: #000000;">start(); } </span>?>
非限定名稱Unqualified name是指名稱中不包含命名空間分隔符的標識符,例如 Foo
限定名稱Qualified name是指名稱中含有命名空間分隔符的標識符,例如 FooBar
完全限定名稱Fully qualified name是指名稱中包含命名空間分隔符,並以命名空間分隔符開始的標識符,例如 FooBar。 namespaceFoo 也是完全限定名稱
如果要動態存取元素(例如,變數函數),必須使用完全限定名稱
<?<span style="color: #000000;">php namespace MyProject; </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> test(){ </span><span style="color: #0000ff;">echo</span> '111'<span style="color: #000000;">; } </span><span style="color: #800080;">$var1</span> = 'test'<span style="color: #000000;">; </span><span style="color: #800080;">$var2</span> = '\MyProject\test'<span style="color: #000000;">; </span><span style="color: #800080;">$var1</span>();<span style="color: #008000;">//</span><span style="color: #008000;">报错</span> <span style="color: #800080;">$var2</span>();/111 ?>
PHP支援兩種抽象的存取目前命名空間內部元素的方法,__NAMESPACE__ 魔術常數和namespace關鍵字
常數__NAMESPACE__的值是包含目前命名空間名稱的字串。在全域的,不包括在任何命名空間中的程式碼,它包含一個空的字串
<?<span style="color: #000000;">php namespace MyProject; </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> test(){ </span><span style="color: #0000ff;">echo</span> '111'<span style="color: #000000;">; } </span><span style="color: #800080;">$var</span> = __NAMESPACE__.'\test'<span style="color: #000000;">; </span><span style="color: #800080;">$var</span>();<span style="color: #008000;">//</span><span style="color: #008000;">111</span> ?>
關鍵字 namespace 可用來明確存取目前命名空間或子命名空間中的元素。它等價於類別中的 self 操作符
<?<span style="color: #000000;">php namespace MyProject; </span><span style="color: #0000ff;">function</span><span style="color: #000000;"> test(){ </span><span style="color: #0000ff;">echo</span> '111'<span style="color: #000000;">; } test();</span><span style="color: #008000;">//</span><span style="color: #008000;">111</span> __NAMESPACE__.test();<span style="color: #008000;">//</span><span style="color: #008000;">111</span> namespace\test();<span style="color: #008000;">//</span><span style="color: #008000;">111</span> ?>
如果沒有定義任何命名空間,所有的類別與函數的定義都是在全局空間,與 PHP 引入命名空間概念前一樣。在名稱前加上前綴 表示該名稱是全域空間中的名稱,即使該名稱位於其它的命名空間中時也是如此
<?<span style="color: #000000;">php namespace A\B\C; </span><span style="color: #008000;">/*</span><span style="color: #008000;"> 这个函数是 A\B\C\fopen </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">function</span> <span style="color: #008080;">fopen</span><span style="color: #000000;">() { </span><span style="color: #008000;">/*</span><span style="color: #008000;"> ... </span><span style="color: #008000;">*/</span> <span style="color: #800080;">$f</span> = \<span style="color: #008080;">fopen</span>(...); <span style="color: #008000;">//</span><span style="color: #008000;"> 调用全局的fopen函数</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$f</span><span style="color: #000000;">; } </span>?>
php允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。这有点类似于在类unix文件系统中可以创建对其它的文件或目录的符号连接
所有支持命名空间的PHP版本支持三种别名或导入方式:为类名称使用别名、为接口使用别名或为命名空间名称使用别名
在PHP中,别名是通过操作符 use 来实现的
别名
<?<span style="color: #000000;">php namespace hello\world\test; </span><span style="color: #0000ff;">use</span> hello\world\test <span style="color: #0000ff;">as</span> t;<span style="color: #008000;">//</span><span style="color: #008000;">用t来替代hello\world\test</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> demo(){ </span><span style="color: #0000ff;">echo</span> '111'<span style="color: #000000;">; } t\demo();</span><span style="color: #008000;">//</span><span style="color: #008000;">111</span> ?>
as可以省略
<?<span style="color: #000000;">php namespace hello\world\test; </span><span style="color: #0000ff;">use</span> hello\world\test;<span style="color: #008000;">//</span><span style="color: #008000;">用test来替代hello\world\test</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> demo(){ </span><span style="color: #0000ff;">echo</span> '111'<span style="color: #000000;">; } test\demo();</span><span style="color: #008000;">//</span><span style="color: #008000;">111</span> ?>
导入
<?<span style="color: #000000;">php </span><span style="color: #0000ff;">use</span><span style="color: #000000;"> \ArrayObject; </span><span style="color: #800080;">$a</span> = <span style="color: #0000ff;">new</span> ArrayObject([]);<span style="color: #008000;">//</span><span style="color: #008000;">若不使用"use \ArrayObject" ,则实例化一个 foo\ArrayObject 对象</span> ?>
为了简化,一行中可以包含多个use语句
<?<span style="color: #000000;">php </span><span style="color: #0000ff;">use</span> My\Full\Classname <span style="color: #0000ff;">as</span> Another,<span style="color: #000000;"> My\Full\NSname; </span><span style="color: #800080;">$obj</span> = <span style="color: #0000ff;">new</span> Another; <span style="color: #008000;">//</span><span style="color: #008000;"> 实例化 My\Full\Classname 对象</span> NSname\subns\func(); <span style="color: #008000;">//</span><span style="color: #008000;"> 调用函数 My\Full\NSname\subns\func</span> ?>