程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> PHP綜合 >> 解析PHP命名空間規則及其高級功能應用

解析PHP命名空間規則及其高級功能應用

編輯:PHP綜合

本文介紹了PHP命名空間的一些術語及其解析規則,以及一些高級功能的應用,希望能夠讓讀者在項目中真正使用命名空間。

在這裡我們介紹了PHP命名空間的用途和namespace關鍵字,為了便於對比,我們定義了兩個幾乎一樣的代碼塊,只有命名空間的名字不同。


1.< ?PHP 
2.// application library 1 
3.namespace App\Lib1; 
4.const MYCONST = 'App\Lib1\MYCONST'; 
5.function MyFunction() { 
6. return __FUNCTION__; 
7.} 
8.class MyClass { 
9. static function WhoAmI() { 
10.eturn __METHOD__; 
11. } 
12.} 
13.?>
 


lib2.PHP


1.< ?PHP 
2.// application library 2 
3.namespace App\Lib2; 
4.
5.const MYCONST = 'App\Lib2\MYCONST'; 
6.
7.function MyFunction() { 
8. return __FUNCTION__; 
9.} 
10.
11.class MyClass { 
12. static function WhoAmI() { 
13.eturn __METHOD__; 
14. } 
15.} 
16.?> 
 


開始之前先要理解幾個PHP命名空間相關術語。

◆完全限定名稱(Fully-qualifIEd name)

任何PHP代碼都可以引用完全限定名稱,它是一個以命名空間反斜線開頭的標識符,如\App\Lib1\MYCONST,\App\Lib2\MyFunction( )等。

完全限定名稱是沒有任何歧義的,開頭的反斜線和文件路徑的作用有點類似,它表示“根”全局空間,如果我們在全局空間中實現了一個不同的MyFunction( ),可以使用\MyFunction( )從lib1.php或lib2.PHP調用它。

完全限定名稱對一次性函數調用或對象初始化非常有用,但當你產生了大量的調用時它們就沒有實用價值了,在下面的討論中我們將會看到,PHP提供了其它選項以解除我們為命名空間打字的煩惱。

◆限定名稱(QualifIEd name)

至少有一個命名空間分隔符的標識符,如Lib1\MyFunction( )。

◆非限定名稱(UnqualifIEd name)

沒有命名空間分隔符的標識符,如MyFunction( )。

在相同的命名空間內工作

仔細思考下面的代碼:

myapp1.PHP


01.< ?PHP 

02.namespace App\Lib1; 

03.

04.require_once('lib1.PHP'); 

05.require_once('lib2.PHP'); 

06.

07.header('Content-type: text/plain'); 

08.echo MYCONST . "\n"; 

09.echo MyFunction() . "\n"; 

10.echo MyClass::WhoAmI() . "\n"; 

11.?>  


即使我們同時包括了lib1.php和lib2.php,MYCONST,MyFunction和MyClass標識符只能在lib1.php中引用,這是因為myapp1.PHP的代碼在相同的App\Lib1命名空間內。

執行結果:

1.App\Lib1\MYCONST 
2.App\Lib1\MyFunction 
3.App\Lib1\MyClass::WhoAmI 
命名空間導入

可以使用use操作符導入命名空間,如:

myapp2.PHP


 


1.< ?PHP 
2.use App\Lib2; 
3.
4.require_once('lib1.PHP'); 
5.require_once('lib2.PHP'); 
6.
7.header('Content-type: text/plain'); 
8.echo Lib2\MYCONST . "\n"; 
9.echo Lib2\MyFunction() . "\n"; 
10.echo Lib2\MyClass::WhoAmI() . "\n"; 
11.?> 
可以定義任意數量的use語句,或使用逗號分隔成獨立的命名空間,在這個例子中我們導入了App\Lib2命名空間,但我們仍然不能直接引用 MYCONST,MyFunction和MyClass,因為我們的代碼還在全局空間中,但如果我們添加了“Lib2\”前綴,它們就變成限定名稱 了,PHP將會搜索導入的命名空間,直到找到匹配項。

執行結果:

1.App\Lib2\MYCONST 
2.App\Lib2\MyFunction 
3.App\Lib2\MyClass::WhoAmI
命名空間別名

命名空間別名可能是最有用的構想了,別名允許我們使用較短的名稱引用很長的命名空間。

myapp3.PHP


1.< ?PHP 
2.use App\Lib1 as L; 
3.use App\Lib2\MyClass as Obj; 
4.
5.header('Content-type: text/plain'); 
6.require_once('lib1.PHP'); 
7.require_once('lib2.PHP'); 
8.
9.echo L\MYCONST . "\n"; 
10.echo L\MyFunction() . "\n"; 
11.echo L\MyClass::WhoAmI() . "\n"; 
12.echo Obj::WhoAmI() . "\n"; 
13.?> 
 


第一個use語句將App\Lib1定義為“L”,任何使用“L”的限定名稱在編譯時都會被翻譯成“App\Lib1”,因此我們就可以引用L\MYCONST和L\MyFunction而不是完全限定名稱了。

第二個use語句定義了“obj”作為App\Lib2\命名空間中MyClass類的別名,這種方式只適合於類,不能用於常量和函數,現在我們就可以使用new Obj( )或象上面那樣運行靜態方法了。

執行結果:

1.App\Lib1\MYCONST 
2.App\Lib1\MyFunction 
3.App\Lib1\MyClass::WhoAmI 
4.App\Lib2\MyClass::WhoAmI 
PHP命名解析規則

PHP標識符名稱使用下列命名空間規則進行解析,請參考PHP用戶手冊了解更詳細的信息:

1.在編譯時調用完全限定函數、類或常量;

2.非限定名稱和限定名稱根據導入規則進行翻譯,例如,如果A\B\C導入為C,調用C\D\e( )就會被翻譯成A\B\C\D\e( );

3.在PHP命名空間內,所有限定名稱尚未根據導入規則轉換,例如,如果在命名空間A\B中調用C\D\e( ),那麼會被翻譯成A\B\C\D\e( );

4.非限定類名稱根據當前的導入規則進行轉換,使用全名替換導入的短名稱,例如,如果類C在命名空間A\B中被導入為X,那麼new X( )就會被翻譯為new A\B\C( );

5.在命名空間中非限定函數調用在運行時解析,例如,如果MyFunction( )在命名空間A\B中被調用,PHP首先會查找函數\A\B\MyFunction( ),如果沒有找到,然後會在全局空間中查找\MyFunction( );

6.調用非限定或限定類名在運行時被解析,例如,如果我們在命名空間A\B中調用new C( ),PHP將會查找類A\B\C,如果沒有找到,PHP會嘗試自動載入A\B\C。


 

PHP命名空間高級特性

接下來讓我們看一看PHP命名空間的一些高級特性。

__NAMESPACE__常量

__NAMESPACE__是一個PHP字符串,它總是返回當前命名空間的名稱,在全局空間中它是一個空字符串。


01.< ?PHP 

02.namespace App\Lib1; 

03.echo __NAMESPACE__; // outputs: App\Lib1 

04.?> 


這個值在調試時非常有用,它也可由於動態生成一個完全限定類名,如:


01.< ?PHP 

02.namespace App\Lib1; 

03.

04.class MyClass { 

05. public function WhoAmI() { 

06.return __METHOD__; 

07. } 

08.} 

09.

10.$c = __NAMESPACE__ . '\\MyClass'; 

11.$m = new $c; 

12.echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI 

13.?>  


namespace關鍵字

namespace關鍵字可以用於明確引用一個當前命名空間或子命名空間中的項目,它等價於類中的self命名空間:


01.< ?PHP 

02.namespace App\Lib1; 

03.

04.class MyClass { 

05. public function WhoAmI() { 

06.return __METHOD__; 

07. } 

08.} 

09.

10.$m = new namespace\MyClass; 

11.echo $m->WhoAmI(); // outputs: App\Lib1\MyClass::WhoAmI 

12.?>  


自動載入命名空間類

PHP 5中最省時省力的特性是自動載入,在全局(非命名空間)PHP代碼中,可以寫一個標准自動載入函數:


01.< ?PHP 

02.$obj= new MyClass1(); // classes/MyClass1.PHP is auto-loaded 

03.$obj= new MyClass2(); // classes/MyClass2.PHP is auto-loaded 

04.

05.// autoload function 

06.function __autoload($class_name) { 

07. require_once("classes/$class_name.PHP"); 

08.} 

09.?>  


在PHP 5.3中,你可以創建一個命名空間類的實例,在這種情況下,完全限定命名空間和類名傳遞給__autoload函數,例如,$class_name的值可 能是App\Lib1\MyClass。你可以在相同的文件夾下放置所有的PHP類文件,從字符串中提取命名空間,但那樣會導致文件名沖突。

另外,你的類文件層次結構會按照命名空間的結構重新組織,例如,MyClass.PHP文件可以創建在/classes/App/Lib1文件夾下:

/classes/App/Lib1/MyClass.PHP


01.< ?PHP 

02.namespace App\Lib1; 

03.

04.class MyClass { 

05. public function WhoAmI() { 

06.return __METHOD__; 

07. } 

08.} 

09.?>  


在根文件夾下的文件就使用下面的代碼了:

myapp.PHP


01.< ?PHP 

02.use App\Lib1\MyClass as MC; 

03.

04.$obj = new MC(); 

05.echo $obj->WhoAmI(); 

06.

07.// autoload function 

08.function __autoload($class) { 

09. // convert namespace to full file path 

10. $class = 'classes/' . str_replace('\\', '/', $class) . '.PHP'; 

11. require_once($class); 

12.} 

13.?>  


解釋:

1.類App\Lib1\MyClass的別名是MC;

2. new MC( )在編譯時被翻譯成new App\Lib1\MyClass( );

3.字符串App\Lib1\MyClass被傳遞給__autoload函數,使用文件路徑正斜線替換所有命名空間中的反斜線,然後修改字符串,classes\App\Lib1\MyClass.PHP文件被自動載入;

總結

有關PHP命名空間的使用就介紹到這裡,希望您能夠對PHP的命名空間有一個新的認識,並希望你能在新項目中真正使用命名空間。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved