名稱空間
根據文件描述,名稱空間設計的目標是用來解決命名衝突的。尤其是在多人合作的模式下,不可避免會出現命名衝突的問題。
名稱空間原理類似 windows 系統下的資料夾,給每個使用者建立一個資料夾,使用者的所有檔案都放在其所屬的資料夾下,這些就可以將不同使用者的檔案彼此隔離開,只需要保證自己名下的檔名唯一,就不會產生命名衝突的問題。
格式要求
- 使用
namespace
關鍵字 -
必須處於檔案的最頂部,前面不能出現任何其他的字元(包括不可見的,空格,回車等),唯一的例外是 PHP 檔案的宣告標籤
<?php
,其他的任何code
都不能在namespace
之前。<?php
namespace xxx;
多層級
名稱空間可以巢狀多層(示例只列舉了兩層),實現類似資料夾巢狀的效果,每一層都是一個範圍(域),同範圍(域)的檔案是可見的,不同層級的檔案則不可見。
<?php
namespace first.econd;
作用域(變數的作用範圍)
PHP 檔案中變數只能在指定的範圍內才存在,範圍被劃分為全域性和區域性,函式外是全域性範圍,函式內是區域性範圍。
<?php
$a = 10;
function test1()
{
$b = 10;
echo $a;
}
echo $b;
如上,$a
是全域性變數,$b
是區域性變數,彼此之間不可用(全域性不能使用區域性變數,區域性不能使用全域性變數)。
test1
中使用 $a
是不可以的,同樣的,在全域性使用 $b
也不可以。
作用域機制決定了變數只能在自己的域中才能被使用。
如果需要跨域使用變數,需要使用 global
關鍵字,將區域性變數轉變成全域性變數之後才能使用。
具體使用
在 1.1 demo 版本中,引入了 namespace
的控制。
app/admin/controller/index.php
引入了名稱空間
<?php
namespace app.dmin.ontroller;
class index
{
...
}
system/url.php
引入了名稱空間
<?php
namespace system;
class url
{
...
}
新增了名稱空間之後,當在 index.php
檔案中引入這些檔案
<?php
...
// 引入路由解析檔案
include('./system/url.php');
...
// 載入指定檔案
include(APP.$obj->get('path').EXT);
...
在使用這些引入檔案中的類,介面,函式和常量時,就有了特別的要求(加了點東西,自然要和之前的情況不一樣)。
這個時候如果以域的視角看,呈現的是下面這個樣子(這是抽象出來的一種模型,有助於理解)
<?php
app
system
xxxx //這裡是 index.php 中的邏輯處理部分
加了 namespace
的檔案,不再可見(結合目錄,可知 app
和 system
下都是有檔案或資料夾的),現在被名稱空間包裹了起來,如果名稱空間有多個層級如 app.ontroller.ndex
,則會有多層包裹,這樣在使用的時候就需要指明所要使用到的函式和類究竟在什麼位置(類似於絕對路徑)。
<?php
...
$obj = new app.ontroller.ndex.ndex();
如上,如果要建立一個 index
控制器下的 index
物件,就需要按照這樣的寫法,系統才能正確的進行定位。
入口檔案 index.php
就是根域可見的一部分,其中的邏輯操作都視為根域下的操作。
當處於一個域之下時,如果不作特別說明,系統預設自帶當前域字首,看如下示例說明
入口檔案index.php
<?php
$a = in_array(); //寫法
---
$a = .n_array(); //實際解析時
應用控制器index.php
<?php
namespace app.dmin.ontroller;
$a = in_array(); //寫法
$b = .n_array(); //這裡顯式指明使用系統函式
---
$a = .pp.dmin.ontroller.n_array(); //實際解析時
回到 namespace
的設計目標,其被設計用來解決命名衝突問題,解決的原理是分配不同的空間,各自在各自的空間內活動,彼此之間不可見,這樣就避免了命名衝突的問題,這是其最重要的作用。
當然在使用時,必須按照正確的方式使用才能確保其生效。正如前面所說的域字首的問題。
PS:本系列文章最佳閱讀方式,IDE + 本地執行環境,IDE 中閱讀可配合 demo 執行增進理解,GitHub 地址