1 命名空間
1.1 概述
<?phpnamespace my\name;class MyClass {}function myfunction() {}const MYCONST = 1;namespace other\name{ //...} $a = new MyClass;$c = new \my\name\MyClass; $a = strlen('hi');$d = namespace\MYCONST;$d = __NAMESPACE__ . '\MYCONST';echo constant($d);?>
上面展示了命名空間相關的概念,下面詳細介紹每個點。
命名空間的定義比較簡單,1 種方式為在頁面的第一行定義 namespace name。若一頁有多個命令空間則推薦使用C++文法的命名空間定義。
層次化命名空間的定義採用路徑格式 level1\level2\level3
1.2 命名空間的使用
假定當前的命名空間為A,則當前空間中出現的名稱在尋找時,都從A\中開始尋找,因此若當前命名空間中定義了與全域空間重名的變數,要訪問全域空間的內容,需要\開始。除非當前命名空間中未定義,從而可以不需要從/開始。
對於沒有定義於全域命名空間的東西,都存在於全域命名空間中。
對於動態使用命名空間的方法如下:
<?phpnamespace namespacename;class classname{ function __construct() { echo __METHOD__,"\n"; }}function funcname(){ echo __FUNCTION__,"\n";}const constname = "namespaced";include 'global.php';$a = 'classname';$obj = new $a; // prints classname::__construct$b = 'funcname';$b(); // prints funcnameecho constant('constname'), "\n"; // prints global/* note that if using double quotes, "\\namespacename\\classname" must be used */$a = '\namespacename\classname';$obj = new $a; // prints namespacename\classname::__construct$a = 'namespacename\classname';$obj = new $a; // also prints namespacename\classname::__construct$b = 'namespacename\funcname';$b(); // prints namespacename\funcname$b = '\namespacename\funcname';$b(); // also prints namespacename\funcnameecho constant('\namespacename\constname'), "\n"; // prints namespacedecho constant('namespacename\constname'), "\n"; // also prints namespaced?>
PHP使用__NAMESPCE__魔術變數及namespace\來儲存當前命名空間的字串,全域命名空間的字串為空白。
1.3 命名空間的匯入
類似於C++,PHP使用use匯入命名空間,同時支援以as的方式為長的命名空間起一個別名,為了簡化,也支援一行匯入多個命名空間。
<?phpnamespace foo;use My\Full\Classname as Another;// 下面的例子與 use My\Full\NSname as NSname 相同use My\Full\NSname;// 匯入一個全域類use \ArrayObject;$obj = new namespace\Another; // 執行個體化 foo\Another 對象$obj = new Another; // 執行個體化 My\Full\Classname 對象NSname\subns\func(); // 調用函數 My\Full\NSname\subns\func$a = new ArrayObject(array(1)); // 執行個體化 ArrayObject 對象// 如果不使用 "use \ArrayObject" ,則執行個體化一個 foo\ArrayObject 對象?>
1.4 命名解析
PHP對於不同的名字有不同的解析尋找策略。
對於類而言,僅僅尋找當前命名空間中類的命名,若要訪問全域命名的類,則需要按完整方式從根\聲明。
對於函數和常量而言,如果當前命名空間中不存在該函數或常量,PHP 會退而使用全域空間中的函數或常量。
1.5 名稱解析規則
- 對完全限定名稱的函數,類和常量的調用在編譯時間解析。例如 new \A\B 解析為類
A\B。
- 所有的非限定名稱和限定名稱(非完全限定名稱)根據當前的匯入規則在編譯時間進行轉換。例如,如果命名空間
A\B\C 被匯入為 C,那麼對 C\D\e() 的調用就會被轉換為 A\B\C\D\e()。
- 在命名空間內部,所有的沒有根據匯入規則轉換的限定名稱均會在其前面加上當前的命名空間名稱。例如,在命名空間
A\B 內部調用 C\D\e(),則 C\D\e() 會被轉換為 A\B\C\D\e() 。
- 非限定類名根據當前的匯入規則在編譯時間轉換(用全名代替短的匯入名稱)。例如,如果命名空間
A\B\C 匯入為C,則 new C() 被轉換為 new A\B\C() 。
- 在命名空間內部(例如A\B),對非限定名稱的函數調用是在運行時解析的。例如對函數
foo() 的調用是這樣解析的:
- 在當前命名空間中尋找名為 A\B\foo() 的函數
- 嘗試尋找並調用 全域(global) 空間中的函數
foo()。
- 在命名空間(例如A\B)內部對非限定名稱或限定名稱類(非完全限定名稱)的調用是在運行時解析的。下面是調用
new C() 及 new D\E() 的解析過程: new C()的解析:
- 在當前命名空間中尋找A\B\C類。
- 嘗試自動裝載類A\B\C。
new D\E()的解析:
- 在類名稱前面加上當前命名空間名稱變成:A\B\D\E,然後尋找該類。
- 嘗試自動裝載類 A\B\D\E。
為了引用全域命名空間中的全域類,必須使用完全限定名稱 new \C()。
2 異常
PHP中引入了類似JAVA等的異常,使用都大同小異,若使用者未捕獲異常,代碼會產生一個異常未捕獲的錯誤,使用者可以定義set_exception_handler()方法來處理這些異常。
使用者定義的異常最好能初始化內建異常。
class MyException extends Exception{ // 重定義構造器使 message 變為必須被指定的屬性 public function __construct($message, $code = 0) { // 自訂的代碼 // 確保所有變數都被正確賦值 parent::__construct($message, $code); } // 自訂字串輸出的樣式 public function __toString() { return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; } public function customFunction() { echo "A Custom function for this type of exception\n"; }}