扣丁學堂詳細解讀PHP的命名空間

本篇文章扣丁學堂小編主要和讀者們詳細解讀一下PHP的命名空間,文中會有詳細的代碼列出供大家參考,下面隨小編一起來了解一下吧。

扣丁學堂詳細解讀PHP的命名空間

PHP培訓

一:命名空間概念:命名空間是一種封裝事物的方法,類似於目錄和文件。

命名空間解決的問題:

1:解決程序編寫者自己寫的類、常量、函數和php內部的或者第三方的出現名稱衝突的情況。

2:創建別名,幫助解決類、常量、函數名稱過長的情況,幫助提高代碼的可讀性,另外名稱過長其實通常都是因為為了緩解第一類問題導致的。

二:如何定義命名空間

1:命名空間用關鍵字namespace聲明,同時命名空間必須位於其他代碼之前,包括任何非php代碼以及空白符(php的declare關鍵字除外),否則會拋出一個fatal error。

例如:

namespace Index;

?>

注意:1:如果命名空間namespace前沒有任何代碼及空白符,但還是出現fatal error,這個應該是由於bom頭導致的,去掉bom頭就可以了。

注意2:在命名空間下,雖然可以放置所有合法的php代碼,但是受命名空間影響的僅有類(抽象類以及traits)和接口、常量和函數。

2:與目錄和文件的關係很象,PHP 命名空間也允許指定層次化的命名空間的名稱。因此,命名空間的名字可以使用分層次的方式定義,分隔符是\。

例如:

namespace Index\Col\File;

define('MESSAGE','hello world');

?>

3:一個文件中可以定義多個命名空間,定義的語法有兩種,一種是簡單組合語法,另一種是大括號形式語法,另外一個文件定義多個命名空間的使用一般是多個文件合併成一個文件的場景,但不到萬不得已最好不要這樣,因為這樣增加了代碼的複雜度,可讀性會降低,一般情況也沒有這種使用的必要。

簡單組合語法:

namespace Index;

const INSTANCE=1;

namespace Col;

const INSTANCE=2;

?>

大括號語法,一個文件多個命名空間,如果還需要寫上非命名空間的代碼,就只能用大括號語法,並且非命名空間代碼用namespace聲明一個沒有名稱的命名空間,再用大括號即可:

/*命名空間Index*/

namespace Index{

const INSTANCE=1;

}

/*命名空間Col*/

namespace Col{

const INSTANCE=2;

}

/*全局非命名空間代碼*/

namespace {

const INSTANCE=3;

}

?>

4:多個不同的文件可以定義同一個命名空間,也就是說同一個命名空間的內容可以分別存儲到多個不同的文件中,這裡就不舉例了。

三:命名空間的識別原理

命名空間的使用原理有三種情況,手冊上其實說的詳細但可能因為翻譯問題導致一些凌亂,這裡簡化一下用自己的例子梳理一下:

1:沒有限定名稱,也就是直接使用要讀取的類、常量、函數、接口名稱,這種情況會讀取該內容所屬的命名空間的類、常量、函數、接口名稱,但如果命名空間內沒有相關的數據,如果是類和接口名稱會返回fatal error,如果是函數和常量會自動讀取全局的函數和常量,如果全局中也沒有,才會報fatal error。

下面舉例:

/*全局非命名空間代碼*/

namespace {

const INSTANCE=1;

function test(){

echo 1;

}

class foo{

static function fool(){

echo 1;

}

}

var_dump(INSTANCE); //打印出來的是1

test(); //輸出1

foo::fool(); //輸出1

}

/*命名空間Index*/

namespace Index{

const INSTANCE=2;

function test(){

echo 2;

}

class foo{

static function fool(){

echo 2;

}

}

var_dump(INSTANCE); //打印出來的是2

test(); //輸出2

foo::fool(); //輸出2

}

/*命名空間Col*/

namespace Col{

const INSTANCE=3;

function test(){

echo 3;

}

class foo{

static function fool(){

echo 3;

}

}

var_dump(INSTANCE); //打印出來的是3

test(); //輸出2

foo::fool(); //輸出2

}

?>

上面的例子每個命名空間裡輸出的都沒有限定名稱,所以會得到當前命名空間下設置的對應數據值。

如果當前命名空間沒有設置,函數和常量則會讀取全局設置的對應數據值,全局沒有對應的才會報fatal error,類和接口都會直接報fatal error,如下面代碼所示。

/*全局非命名空間代碼*/

namespace {

const INSTANCE=1;

function test(){

echo 1;

}

class foo{

static function fool(){

echo 1;

}

}

var_dump(INSTANCE); //打印出來的是1

test(); //輸出1

foo::fool(); //輸出1

}

/*命名空間Index*/

namespace Index{

var_dump(INSTANCE); //打印出來的是1

test(); //輸出1

foo::fool(); //fatal error

}

?>

2:限定名稱,分為兩種情況,一種是包含前綴的限定名稱情況,一種是包含全侷限定名稱的情況。手冊上將這兩種單獨分開了,但我覺得這兩種可以合併成一起說,他們都是有限定名稱,只是前者沒有全侷限定,後者有全侷限定。

①包含前綴的限定名稱,這種前綴可以有多個或者一個層級,但最左側不能為\全侷限定詞,這種情況會讀取該代碼所在命名空間加上該前綴限定名稱所對應數據,也就是:

所處命名空間\前綴限定\名稱來讀取,如果該代碼是全局沒有命名空間的,則直接用前綴限定名稱來讀取,也就是:前綴限定\名稱來讀取。

實例代碼:

/*命名空間Col\Index*/

namespace Col\Index{

const INSTANCE=1;

}

/*命名空間Index*/

namespace Index{

const INSTANCE=2;

}

/*命名空間Col*/

namespace Col{

const INSTANCE=3;

var_dump(Index\INSTANCE); //打印出來的是1 讀取的是Col\Index\INSTANCE

}

/*全局非命名空間代碼*/

namespace {

const INSTANCE=4;

var_dump(Index\INSTANCE); //打印出來的是2 讀取的是Index\INSTANCE

}

?>

②全侷限定前綴名稱:也就是在最左側有全局操作符\進行修飾的前綴限定名稱,當然也可以沒有前綴限定直接全局操作符\加上名稱也是可以的。但加上全局操作符後就跟目錄裡的絕對路徑一樣,只會按照全侷限定後的所設置的進行讀取。

具體實例如下:

/*命名空間Col\Index*/

namespace Col\Index{

const INSTANCE=1;

}

/*命名空間Index*/

namespace Index{

const INSTANCE=2;

}

/*命名空間Col*/

namespace Col{

const INSTANCE=3;

var_dump(\Index\INSTANCE); //打印出來的是2 讀取的是Index\INSTANCE

}

/*全局非命名空間代碼*/

namespace {

const INSTANCE=4;

var_dump(\Index\INSTANCE); //打印出來的是2 讀取的是Index\INSTANCE

}

namespace Lin{

const INSTANCE=5;

var_dump(\INSTANCE); //打印出來的是4 讀取的是INSTANCE,是全局非命名空間裡的INSTANCE,如果沒有全局操作符\,讀取的會是當前命名空間的Lin\INSTANCE=5

}

?>

四:命名空間在字符串中的轉義

有時候命名空間會放在字符串中使用,如果是單引號不會通過編譯器解釋,所以沒有任何問題,但是如果是雙引號,那麼就會有些意外情況了,要知道雙引號裡的內容是需要經過編譯器進行解釋然後再進行輸出的,而\在編譯器裡的解釋容易造成歧義。

例如"index\name"這裡就有\n會被解釋成換行,除此之外還有很多這種造成意外的情況。

因此一般我們推薦命名空間如果要放在字符串中使用,最好使用單引號,一是效率,二是安全,如果使用雙引號,則必須增加一個\進行轉義避免歧義,例如"index\\name"這樣就沒有問題了。

隨手雙引號的舉個例子:

/*全局非命名空間代碼*/

namespace Index\Name{

class foo{

function __construct(){

echo 2;

}

}

}

namespace{

$a= "Index\\Name\\foo"; //用\轉義了\所以可以正常運行,但是如果去掉轉義的話會報錯Class 'Index\Nameoo',因為/f被解釋成了換頁符

$obj=new $a;

}

以上就是小編給大家分享的解讀PHP的命名空間,希望對小夥伴們有所幫助,想要了解更多內容的小夥伴可以登錄扣丁學堂官網諮詢。扣丁學堂是專業的PHP培訓機構,不僅有專業的老師和與時俱進的課程體系,還有大量的PHP視頻教程供學員觀看學習哦,心動的小夥伴快快行動吧。


分享到:


相關文章: