首頁  >  文章  >  後端開發  >  PHP-命名空間(namespace)使用詳細介紹

PHP-命名空間(namespace)使用詳細介紹

王林
王林轉載
2019-08-28 16:01:422016瀏覽

對於命名空間,官方文件已經說得很詳細[查看],我在這裡做了實踐和總結。

命名空間一個最明確的目的就是解決重名問題,PHP不允許兩個函數或類別出現相同的名字,否則會產生一個致命的錯誤。這種情況只要避免命名重複就可以解決,最常見的做法就是約定一個前綴。

範例:專案中有兩個模組:article和message board,它們各自有一個處理使用者留言的類別Comment。之後我可能想要增加對所有用戶留言的一些資訊統計功能,例如說我想得到所有留言的數量。這時候呼叫它們Comment提供的方法是很好的做法,但是同時引入各自的Comment類別顯然是不行的,程式碼會出錯,在另一個地方重寫任何一個Comment也會降低維護性。那這時只能重構類別名,我約定了一個命名規則,在類別名稱前面加上模組名,像這樣:Article_Comment、MessageBoard_Comment

可以看到,名字變得很長,那意味著以後使用Comment的時候會寫更多的程式碼(至少字元多了)。並且,以後如果要對各個模組增加更多的一些整合功能,或者是互相調用,發生重名的時候就需要重構名字。當然在專案開始的時候就注意到這個問題,並規定命名規則就能很好的避免這個問題。另一個解決方法可以考慮使用命名空間。

註明:

本文提到的常數:PHP5.3開始const關鍵字可以用在類別的外部。 const和define都是用來聲明常數的(它們的區別不詳述),但是在命名空間裡,define的作用是全局的,而const則作用於當前空間。我在文中提到的常數是指使用const宣告的常數。

基礎:

命名空間將程式碼分割出不同的空間(區域),每個空間的常數、函數、類別(為了偷懶,我下邊都稱它們為元素)的名字互不影響, 這個有點類似我們常常提到的'封裝'的概念。

建立一個命名空間需要使用namespace關鍵字

程式碼如下:

要注意的是,目前腳本檔案的第一個命名空間前面不能有任何程式碼,下面的寫法都是錯誤的:

程式碼如下:

//在脚本前面写了一些逻辑代码

或如下:

//在脚本前面输出了一些字符

為什麼要說第一個命名空間呢?因為在同一腳本檔案中可以建立多個命名空間。

下面我建立了兩個命名空間,順便為這兩個空間各自添加了一個Comment類別元素:

程式碼如下:

在不同空間之間不可以直接呼叫其它元素,需要使用命名空間的語法:

程式碼如下:

可以看到,在MessageBoard空間中呼叫article空間裡的Comment類別時,使用了一種像檔案路徑的語法: \空間名稱\元素名稱

除了類別之外,對函數和常數的用法是一樣的,下面我為兩個空間創建了新的元素,並在MessageBoard空間中輸出了它們的值。

程式碼如下:

子空間:

#命名空間的呼叫語法像檔案路徑一樣是有道理的,它允許我們自訂子空間來描述各個空間之間的關係。

抱歉我忘了說,article和message board這兩個模組其實都是處於同一個blog專案內。如果用命名空間來表達它們的關係

公共空間

我有一個common_inc.php腳本文件,裡面有一些好用的函數和類別:

在一個命名空間裡引入這個腳本,腳本裡的元素不會歸屬到這個命名空間。如果這個腳本裡沒有定義其它命名空間,它的元素就始終處於公共空間中:

調用公共空間的方式是直接在元素名稱前加\ 就可以了,否則PHP解析器會認為我想調用當前空間下的元素。除了自訂的元素,還包括PHP自帶的元素,都屬於公共空間

要提一下,其實公共空間的函數和常數不用加\ 也可以正常調用(不明白PHP為什麼要這樣做),但是為了正確區分元素,還是建議呼叫函數的時候加上\

3、名稱術語

在說別名和導入之前,需要知道關於空間三種名稱的術語,以及PHP是怎麼解析它們的。官方文件說得非常好,我就直接拿來套了。

1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是Blog\Article,Comment将被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

2.限定名称,或包含前缀的名称,例如 $comment = new Article\Comment();。如果当前的命名空间是Blog,则Comment会被解析为Blog\Article\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。

3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \Article\Comment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)Article\Comment。

其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

我用了几个示例来表示它们:

别名和导入
别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。

它们都是通过使用use操作符来实现

代码如下:

我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。

动态调用
PHP提供了namespace关键字和__NAMESPACE__魔法常量动态的访问元素,__NAMESPACE__可以通过组合字符串的形式来动态访问

字符串形式调用问题:

上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题

1、使用""时特殊字符可能被转义

2、不会认为是限定名称

PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称

总结
我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

更多相关问题请访问PHP中文网:PHP视频教程

以上是PHP-命名空間(namespace)使用詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除