< ?php // application library 1 namespace AppLib1; const MYCONST = 'AppLib1MYCONST'; function MyFunction() { return __FUNCTION__; } class MyClass { static function WhoAmI() { eturn __METHOD__; } } ?> lib2.php
< ?php // application library 2 namespace AppLib2; const MYCONST = 'AppLib2MYCONST'; function MyFunction() { return __FUNCTION__; } class MyClass { static function WhoAmI() { eturn __METHOD__; } } ?> 開始之前先要理解幾個PHP命名空間相關術語。
◆完全限定名稱(Fully-qualified name)
任何PHP代碼都可以引用完全限定名稱,它是一個以命名空間反斜線開頭的標識符,如AppLib1MYCONST,AppLib2MyFunction( )等。
完全限定名稱是沒有任何歧義的,開頭的反斜線和文件路徑的作用有點類似,它表示“根”全局空間,如果我們在全局空間中實現了一個不同的MyFunction( ),可以使用MyFunction( )從lib1.php或lib2.php調用它。
完全限定名稱對一次性函數調用或對象初始化非常有用,但當你產生了大量的調用時它們就沒有實用價值了,在下面的討論中我們將會看到,PHP提供了其它選項以解除我們為命名空間打字的煩惱。
◆限定名稱(Qualified name)
至少有一個命名空間分隔符的標識符,如Lib1MyFunction( )。
◆非限定名稱(Unqualified name)
沒有命名空間分隔符的標識符,如MyFunction( )。
在相同的命名空間內工作
仔細思考下面的代碼:
myapp1.php
< ?php namespace AppLib1; require_once('lib1.php'); require_once('lib2.php'); header('Content-type: text/plain'); echo MYCONST . "n"; echo MyFunction() . "n"; echo MyClass::WhoAmI() . "n"; ?> 即使我們同時包括了lib1.php和lib2.php,MYCONST,MyFunction和MyClass標識符只能在lib1.php中引用,這是因為myapp1.php的代碼在相同的AppLib1命名空間內。
執行結果:
AppLib1MYCONST AppLib1MyFunction AppLib1MyClass::WhoAmI 命名空間導入
可以使用use操作符導入命名空間,如:
myapp2.php
< ?php use AppLib2; require_once('lib1.php'); require_once('lib2.php'); header('Content-type: text/plain'); echo Lib2MYCONST . "n"; echo Lib2MyFunction() . "n"; echo Lib2MyClass::WhoAmI() . "n"; ?> 可以定義任意數量的use語句,或使用逗號分隔成獨立的命名空間,在這個例子中我們導入了AppLib2命名空間,但我們仍然不能直接引用MYCONST,MyFunction和MyClass,因為我們的代碼還在全局空間中,但如果我們添加了“Lib2”前綴,它們就變成限定名稱了,PHP將會搜索導入的命名空間,直到找到匹配項。
執行結果:
AppLib2MYCONST AppLib2MyFunction AppLib2MyClass::WhoAmI 命名空間別名
命名空間別名可能是最有用的構想了,別名允許我們使用較短的名稱引用很長的命名空間。
myapp3.php
< ?php use AppLib1 as L; use AppLib2MyClass as Obj; header('Content-type: text/plain'); require_once('lib1.php'); require_once('lib2.php'); echo LMYCONST . "n"; echo LMyFunction() . "n"; echo LMyClass::WhoAmI() . "n"; echo Obj::WhoAmI() . "n"; ?> 第一個use語句將AppLib1定義為“L”,任何使用“L”的限定名稱在編譯時都會被翻譯成“AppLib1”,因此我們就可以引用LMYCONST和LMyFunction而不是完全限定名稱了。
第二個use語句定義了“obj”作為AppLib2命名空間中MyClass類的別名,這種方式只適合於類,不能用於常量和函數,現在我們就可以使用new Obj( )或象上面那樣運行靜態方法了。
執行結果:
AppLib1MYCONST AppLib1MyFunction AppLib1MyClass::WhoAmI AppLib2MyClass::WhoAmI PHP命名解析規則
PHP標識符名稱使用下列命名空間規則進行解析,請參考PHP用戶手冊了解更詳細的信息:
1.在編譯時調用完全限定函數、類或常量;
2.非限定名稱和限定名稱根據導入規則進行翻譯,例如,如果ABC導入為C,調用CDe( )就會被翻譯成ABCDe( );
3.在PHP命名空間內,所有限定名稱尚未根據導入規則轉換,例如,如果在命名空間AB中調用CDe( ),那麼會被翻譯成ABCDe( );
4.非限定類名稱根據當前的導入規則進行轉換,使用全名替換導入的短名稱,例如,如果類C在命名空間AB中被導入為X,那麼new X( )就會被翻譯為new ABC( );
5.在命名空間中非限定函數調用在運行時解析,例如,如果MyFunction( )在命名空間AB中被調用,PHP首先會查找函數ABMyFunction( ),如果沒有找到,然後會在全局空間中查找MyFunction( );
6.調用非限定或限定類名在運行時被解析,例如,如果我們在命名空間AB中調用new C( ),PHP將會查找類ABC,如果沒有找到,PHP會嘗試自動載入ABC
PHP命名空間高級特性
接下來讓我們看一看PHP命名空間的一些高級特性。
__NAMESPACE__常量
__NAMESPACE__是一個PHP字符串,它總是返回當前命名空間的名稱,在全局空間中它是一個空字符串。
< ?php namespace AppLib1; echo __NAMESPACE__; // outputs: AppLib1 ?> 這個值在調試時非常有用,它也可由於動態生成一個完全限定類名,如:
< ?php namespace AppLib1; class MyClass { public function WhoAmI() { return __METHOD__; } } $c = __NAMESPACE__ . '\MyClass'; $m = new $c; echo $m->WhoAmI(); // outputs: AppLib1MyClass::WhoAmI ?> namespace關鍵字
namespace關鍵字可以用於明確引用一個當前命名空間或子命名空間中的項目,它等價於類中的self命名空間:
< ?php namespace AppLib1; class MyClass { public function WhoAmI() { return __METHOD__; } } $m = new namespaceMyClass; echo $m->WhoAmI(); // outputs: AppLib1MyClass::WhoAmI ?> 自動載入命名空間類
PHP 5中最省時省力的特性是自動載入,在全局(非命名空間)PHP代碼中,可以寫一個標准自動載入函數:
< ?php $obj= new MyClass1(); // classes/MyClass1.php is auto-loaded $obj= new MyClass2(); // classes/MyClass2.php is auto-loaded // autoload function function __autoload($class_name) { require_once("classes/$class_name.php"); } ?> 在PHP 5.3中,你可以創建一個命名空間類的實例,在這種情況下,完全限定命名空間和類名傳遞給__autoload函數,例如,$class_name的值可能是AppLib1MyClass。你可以在相同的文件夾下放置所有的PHP類文件,從字符串中提取命名空間,但那樣會導致文件名沖突。
另外,你的類文件層次結構會按照命名空間的結構重新組織,例如,MyClass.php文件可以創建在/classes/App/Lib1文件夾下:
/classes/App/Lib1/MyClass.php
< ?php namespace AppLib1; class MyClass { public function WhoAmI() { return __METHOD__; } } ?> 在根文件夾下的文件就使用下面的代碼了:
myapp.php
< ?php use AppLib1MyClass as MC; $obj = new MC(); echo $obj->WhoAmI(); // autoload function function __autoload($class) { // convert namespace to full file path $class = 'classes/' . str_replace('\', '/', $class) . '.php'; require_once($class); } ?> 解釋:
1.類AppLib1MyClass的別名是MC;
2. new MC( )在編譯時被翻譯成new AppLib1MyClass( );
3.字符串AppLib1MyClass被傳遞給__autoload函數,使用文件路徑正斜線替換所有命名空間中的反斜線,然後修改字符串,classesAppLib1MyClass.php文件被自動載入;
總結
有關PHP命名空間的使用就介紹到這裡,希望您能夠對PHP的命名空間有一個新的認識,並希望你能在新項目中真正使用命名空間。