namespace

PHP命名空間

一種封裝事物的方法,原理類似於操作系統中使用目錄來對文件分組

解決問題

  1. 用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字衝突。
  2. 爲很長的標識符名稱(通常是爲了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高源代碼的可讀性。

定義

<?php
namespace  MyProject ;  // 所有非 PHP 代碼包括空白符都不能出現在命名空間的聲明之前(declare 語句除外)

// 只有類,函數,常量的代碼受命名空間的影響
const  CONNECT_OK  =  1 ;
class  Connection  {  /* ... */  }
function  connect () {  /* ... */   }

全局空間

如果沒有定義任何命名空間,所有的類與函數的定義都是在全局空間,與 PHP 引入命名空間概念前一樣。

在名稱前加上前綴 \ 表示該名稱是全局空間中的名稱,即使該名稱位於其它的命名空間中時也是如此。

多層命名空間

<?php
 namespace  MyProject \ Sub \ Level ; // 定義的分層次的命名空間,對應相應的目錄結構

const  CONNECT_OK  =  1 ;
class  Connection  {  /* ... */  }
function  connect () {  /* ... */   }

多命名空間

在實際的編程實踐中,將多個 PHP 腳本合併在同一個文件中(非常不提倡在同一個文件中定義多個命名空間)

<?php
namespace  MyProject  {

const  CONNECT_OK  =  1 ;
class  Connection  {  /* ... */  }
function  connect () {  /* ... */   }
}

// 使用兩個大括號分隔
namespace  AnotherProject  { 

const  CONNECT_OK  =  1 ;
class  Connection  {  /* ... */  }
function  connect () {  /* ... */   }
}

// 如果不指定命名空間名稱,則爲全局代碼
namespace {  // 全局代碼
session_start ();
$a  =  MyProject \ connect ();
echo  MyProject \ Connection :: start ();
}
 ?> 

use

支持導入類或命名空間。但PHP不支持導入函數或常量。

因爲導入的名稱必須是完全限定的(不會根據當前的命名空間作相對解析),所以導入的前導反斜槓是不必要的也不允許有反斜槓。

<?php
namespace  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 對象

命名空間使用

非限定名稱

名稱中不包含命名空間分隔符的標識符

$a=new foo();
foo::staticmethod();

如果當前命名空間是 currentnamespace,foo 將被解析爲 currentnamespace\foo。

如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,則 foo 會被解析爲foo。

警告:如果命名空間中的函數或常量未定義,則該非限定的函數名稱或常量名稱會被解析爲全局函數名稱或常量名稱。

限定名稱

名稱中含有命名空間分隔符的標識符

$a = new subnamespace\foo();
subnamespace\foo::staticmethod();

如果當前的命名空間是 currentnamespace,則 foo 會被解析爲 currentnamespace\subnamespace\foo。

如果使用 foo 的代碼是全局的,不包含在任何命名空間中的代碼,foo 會被解析爲subnamespace\foo。

完全限定名稱

名稱以命名空間分隔符開始的標識符,例如 \Foo\Bar。 namespace\Foo 也是一個完全限定名稱。

$a = new \currentnamespace\foo();
\currentnamespace\foo::staticmethod();

在這種情況下,foo 總是被解析爲代碼中的文字名(literal name)currentnamespace\foo。

導入和別名解析

根據當前的導入規則在編譯時進行轉換。

例如,命名空間 A\B\C 被導入爲 C,那麼對 C\D\e() 的調用就會被轉換爲 A\B\C\D\e()

解析順序

類名稱總是解析到當前命名空間中的名稱。因此在訪問系統內部或不包含在命名空間中的類名稱時,必須使用完全限定名稱

<?php
 namespace  A \ B \ C ;
class  Exception  extends \ Exception  {}

 $a  = new  Exception ( 'hi' );  // $a 是類 A\B\C\Exception 的一個對象
 $b  = new \ Exception ( 'hi' );  // $b 是類 Exception 的一個對象

 $c  = new  ArrayObject ;  // 致命錯誤, 找不到 A\B\C\ArrayObject 類
 ?>

函數和常量:如果當前命名空間中不存在該函數或常量,PHP 會退而使用全局空間中的函數或常量

常量

__NAMESPACE__ 當前命名空間名稱的字符串

<?php
 namespace  MyProject ;

echo  '"' ,  __NAMESPACE__ ,  '"' ;  // 輸出 "MyProject"
 ?> 

namespace 顯式訪問當前命名空間或子命名空間中的元素。

<?php

namespace\ func ();  // calls function func()
namespace\ sub \ func ();  // calls function sub\func()
namespace\ cname :: method ();  // calls static method "method" of class cname
$a  = new namespace\ sub \ cname ();  // instantiates object of class sub\cname
$b  = namespace\ CONSTANT ;  // assigns value of constant CONSTANT to $b
?> 

::class 返回類 ClassName 的完全限定名稱

<?php
namespace  NS  {
    class  ClassName  {
    }

    echo  ClassName ::class; //輸出 NS\ClassName
}
?> 

PHP官方手冊 http://php.net/manual/zh/language.namespaces.php

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章