PHP名稱空間

十萬馬發表於2019-02-16

*名稱空間的支援版本:PHP 5 > 5.3.0,PHP 7 。

什麼是名稱空間

從廣義上來說,名稱空間是一種封裝事物的方法。在很多地方都可以見到這種抽象概念。例如,在作業系統中目錄用來將相關檔案分組,對於目錄中的檔案來說,它就扮演了名稱空間的角色。具體舉個例子,檔案 foo.txt 可以同時在目錄/home/greg 和 /home/other 中存在,但在同一個目錄中不能存在兩個 foo.txt 檔案。另外,在目錄 /home/greg 外訪問 foo.txt 檔案時,我們必須將目錄名以及目錄分隔符放在檔名之前得到 /home/greg/foo.txt。這個原理應用到程式設計領域就是名稱空間的概念。

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

使用者編寫的程式碼與PHP內部的類/函式/常量或第三方類/函式/常量之間的名字衝突。
為很長的識別符號名稱(通常是為了緩解第一類問題而定義的)建立一個別名(或簡短)的名稱,提高原始碼的可讀性。
PHP 名稱空間提供了一種將相關的類、函式和常量組合到一起的途徑。

定義名稱空間

名稱空間通過關鍵字namespace 來宣告。宣告名稱空間的語句必須是檔案的第一行語句,除了一個以外:declare關鍵字。在宣告名稱空間之前唯一合法的程式碼是用於定義原始檔編碼方式的 declare 語句。另外,所有非 PHP 程式碼包括空白符都不能出現在名稱空間的宣告之前。同一個名稱空間可以定義在多個檔案中,即允許將同一個名稱空間的內容分割存放在不同的檔案中。

namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

?>

同目錄具有層次結構類似,名稱空間也支援指定層次化的名稱空間名稱。

<?php
namespace MyProjectSubLevel;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
?>

上面的例子建立了常量MyProjectSubLevelCONNECT_OK,類 MyProjectSubLevelConnection和函式 MyProjectSubLevelconnect。

PHP還支援在同一個檔案中定義不同的名稱空間,但是非常不建議這種用法,這裡就不多說了。

這裡我有一個疑問,上面說名稱空間定義必須是檔案的第一行程式碼,那在一個檔案中定義多個名稱空間不就是會出現不在第一行的情況?

針對這個問題試驗了一下,對於一個檔案中包含多個名稱空間的,必須所有的程式碼都在某一個名稱空間中,否則就會報 Fatal error: No code may exist outside of namespace {} in 的錯誤,對於全域性程式碼,那就放在全域性的名稱空間中,類似這樣 namespace { }

使用名稱空間

PHP 名稱空間中的元素可以通過三種方式引用,以類名為例:

非限定名稱,或不包含字首的類名稱,例如 $a=new foo(); 或 foo::staticmethod();。如果當前名稱空間是 currentnamespace,foo 將被解析為 currentnamespacefoo。如果使用 foo 的程式碼是全域性的,不包含在任何名稱空間中的程式碼,則 foo 會被解析為foo。 警告:如果名稱空間中的函式或常量未定義,則該非限定的函式名稱或常量名稱會被解析為全域性函式名稱或常量名稱。詳情參見 使用名稱空間:後備全域性函式名稱/常量名稱。
限定名稱,或包含字首的名稱,例如 $a = new subnamespacefoo(); 或 subnamespacefoo::staticmethod();。如果當前的名稱空間是 currentnamespace,則 foo 會被解析為 currentnamespacesubnamespacefoo。如果使用 foo 的程式碼是全域性的,不包含在任何名稱空間中的程式碼,foo 會被解析為subnamespacefoo。
完全限定名稱,或包含了全域性字首操作符的名稱,例如, $a = new currentnamespacefoo(); 或 currentnamespacefoo::staticmethod();。在這種情況下,foo 總是被解析為程式碼中的文字名(literal name)currentnamespacefoo。
NAMESPACE常量

常量__NAMESPACE__的值是包含當前名稱空間名稱的字串。在全域性的,不包括在任何名稱空間中的程式碼,它包含一個空的字串。

namespace 關鍵字

關鍵字 namespace 可用來顯式訪問當前名稱空間或子名稱空間中的元素。它等價於類中的 self 操作符。

使用名稱空間

所有支援名稱空間的PHP版本支援三種別名或匯入方式:為類名稱使用別名、為介面使用別名或為名稱空間名稱使用別名。PHP 5.6開始允許匯入函式或常量或者為它們設定別名。在PHP中,別名是通過操作符 use 來實現的.

namespace foo;
use MyFullClassname as Another;

// 下面的例子與 use MyFullNSname as NSname 相同
use MyFullNSname;

// 匯入一個全域性類
use ArrayObject;

// importing a function (PHP 5.6+)
use function MyFullfunctionName;

// aliasing a function (PHP 5.6+)
use function MyFullfunctionName as func;

// importing a constant (PHP 5.6+)
use const MyFullCONSTANT;

$obj = new namespaceAnother; // 例項化 fooAnother 物件
$obj = new Another; // 例項化 MyFullClassname 物件
NSnamesubnsfunc(); // 呼叫函式 MyFullNSnamesubnsfunc
$a = new ArrayObject(array(1)); // 例項化 ArrayObject 物件
// 如果不使用 "use ArrayObject" ,則例項化一個 fooArrayObject 物件
func(); // calls function MyFullfunctionName
echo CONSTANT; // echoes the value of MyFullCONSTANT
?>```
注意對名稱空間中的名稱(包含名稱空間分隔符的完全限定名稱如 FooBar以及相對的不包含名稱空間分隔符的全域性名稱如 FooBar)來說,前導的反斜槓是不必要的也不推薦的,因為匯入的名稱必須是完全限定的,不會根據當前的名稱空間作相對解析。為了簡化操作,PHP還支援在一行中使用多個use語句。

相關文章