關於PHP命名空間的討論

  • 2020 年 3 月 14 日
  • 筆記

什麼是命名空間?

    根據php.net官方翻譯文檔描述,命名空間是這樣定義的:

什麼是命名空間?從廣義上來說,命名空間是一種封裝事物的方法。

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

(1)、用戶編寫的程式碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字衝突。

(2)為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高源程式碼的可讀性。

    這個描述太官方,不太好懂。

    簡單地說,這個命名空間,就是用來解決定義的常量、函數和類,存在重名的問題,一是解決用戶定義的類/函數/常量與PHP內部的類/函數/常量同名的問題,二是解決不同軟體開發小組或不同軟體公司定義的類/函數/常量同名的問題,而你需要同時使用這兩個公司定義的類庫。

    比如,新冠肺炎防控期間,Ahcme學校開發了用於收集學生疫情報告的資訊的軟體平台,AnHui省也開發了省級疫情監測平台,用於匯總各高校疫情資訊進行大數據分析和預警。現在,由Wisedu公司來做這個對接開發,用於將ahcme學校的填報明細數據每天定時上傳到省級疫情平台。

    在Wisedu公司開始做對接工作之前,Ahcme學校和Anhui省都已經基本完成了程式碼開發,他們有了下面的php程式碼文件:

Achme學校的程式碼是 ahcme_sample.php文件:

 

Anhui省的程式碼是 anhui_sample.php文件:

 

    這兩個單位的程式碼都定義了同樣名字的常量、函數和類,但具體的實現細節是不一樣的。現在wisedu公司要做的事情就是要將ahcme的學生資訊轉換成anhui省監控平台所需要的數據格式,以便進行數據上報。

Wisedu公司寫了下面的測試程式碼(test.php):

 

    這樣帶來一個問題,調用hello函數和實例化Student對象,我不知道是使用的是ahcme學校的程式碼,還是anhui省的程式碼。更嚴重的是,運行會報錯:

 

    這是一個嚴重錯誤(Fatal error),提示是不能重複定義hello函數。當然也會遇到類Student不能重複定義。

    怎麼解決這個問題呢?那就是給ahcme學校和anhui省的程式碼,定義在不同的命名空間裡面。

如何定義命名空間?

    使用namespace關鍵字定義命名空間。

    namespace語句必須是php文件中<?php標記下的第1個語句(declare語句除外)。

    頂級命名空間是,接下來是一級命名空間,二級命名空間,他們之間用分隔。

    如ncov2019ahcme就是一個二級命名空間,是ncov2019命名空間的子命名空間。

Achme學校的程式碼是 ahcme_sample.php文件:

 

Anhui省的程式碼是 anhui_sample.php文件:

 

    這裡使用的是二級子命名空間,可以認為這兩個單位的項目都是新冠肺炎防控(ncov2019)這個項目的子項目。當然你也可以使用一級命名空間(如anhui和ahcme),這由這幾個開發小組共同協商好就行。

    不建議在一個php文件中定義多個命名空間。

    這個時候,wisedu公司的測試程式碼就可以這樣寫:

 

    這裡,test.php沒有定義命名空間,那他是頂級命名空間。那麼當前命名空間就是。

    這樣,就能很清楚的知道,$s1對象是ahcme學校的學生,$s2對象是anhui省的大學生了。運行結果也是這樣:

 

當然,作為wisedu公司的程式碼,他也可以定義命名空間:

 

    這時,當前命名空間就是ncov2019wisedu了。不能再像這樣去定義ahcme的Student對象了:

$s1 = new ncov2019ahcmeStudent(“11001”, “張三”);

    因為上面是相對路徑的定法。以前當前命名空間是,轉換成絕對路徑是ncov2019ahcmeStudent對象,是正確的。現在當前命名空間是ncov2019wisedu,轉換成絕對路徑就是ncov2019wiseduncov2019ahcmeStudent對象,當然就不正確了,所以要用絕對路徑來使用Student對象:

$s1 = new ncov2019ahcmeStudent(“11001”, “張三”);

給命名空間起個別名

    上面的命名空間ncov2019wiseduncov2019ahcme名字太長,經常寫的話就很費事,所以打算用個短點的名字,如ahcme。這是可以使用use關鍵字來給命名空間起個別名:

 

除了可以使用use語句給命名空間起別名,也可以給常量、函數、類名起個別名:

  

    總之,命名空間就是用來解決不同軟體開發團隊間常量/函數/類的同名問題。如果遇不到命名衝突問題,完全可以不使用命名空間。

    另外,PHP的命名空間是從5.3版本才開始的,從個人感覺來看,他的命名空間解決機制沒有Java和.NET的豐富和靈活。從總體來看,PHP沒有多少如淘寶、Youtube等大型項目的應用,他的主要應用還是在於中小型項目的快速構建,所以,它在一些複雜項目的管理支援上還是要欠缺一些。

    有問題,請在下方評論區留言。

(2020.3.14 0:48 by whitewin)