新時(shí)代PHP:命名空間

前言

命名空間不算新東西了,在PHP5.3.0之后就存在。曾經(jīng)學(xué)次c#的時(shí)候接觸過(guò)命名空間這個(gè)概念剑刑,后來(lái)發(fā)現(xiàn)php也出現(xiàn)墨吓,但是當(dāng)時(shí)認(rèn)為\符號(hào)來(lái)使用命名空間很丑陋球匕,一直不敢興趣,現(xiàn)在我覺(jué)得\符越來(lái)越好看帖烘,人的眼光總是在進(jìn)步亮曹。

命名空間是新時(shí)代PHP不可或缺的一部分,它是現(xiàn)代主流php框架的基石秘症。

什么是命名空間

說(shuō)白了照卦,命名空間是解決文件、函數(shù)乡摹、類(lèi)役耕、常量等的重名問(wèn)題,它虛擬了類(lèi)似操作系統(tǒng)中文件系統(tǒng)的目錄結(jié)構(gòu)聪廉,保證PHP組件和框架的全局唯一瞬痘。

比如我在在a目錄下有個(gè)db.php,在b目錄下也有個(gè)db.php板熊。那么按照古老的方式肯定是通過(guò)類(lèi)名保持和文件一致來(lái)區(qū)別.

例如a目錄下的命名為:

class A_DB{}

b目錄下的命名為:

class B_DB{}

編寫(xiě)函數(shù)時(shí)可能通過(guò)每次加上一個(gè)function_exist的判斷去定義是否重名框全。
常量的定義同理,都是可以有解決沖突的方案干签,但是現(xiàn)在composer盛行津辩,PHP生態(tài)環(huán)境極好,各種組件層出不窮,我們不能保證所有組件的命名都不一樣喘沿,并且這種通過(guò)文件名和類(lèi)名來(lái)做區(qū)分十分不優(yōu)雅情萤,如果目錄層級(jí)很深,那么類(lèi)名可能會(huì)十分冗長(zhǎng)摹恨。顯然筋岛,我們應(yīng)該選擇更先進(jìn)的方法。

聲明命名空間

每個(gè)php文件的第一個(gè)命名空間必須聲明在php的頂部晒哄,在<?php標(biāo)簽之后的第一行做聲明睁宰。命名空間是通過(guò)namespace聲明,然后跟上一個(gè)空格寝凌,再然后跟上命名空間的名稱(chēng)柒傻,最后用;符號(hào)結(jié)尾。

例如较木,聲明一個(gè)名稱(chēng)為A的命名空間:

<?php
namespace A; 

在這個(gè)命名空間后面的所有php類(lèi)红符,函數(shù),接口伐债,常量都在這個(gè)A命名空間里面预侯。

同一個(gè)文件中定義多個(gè)命名空間

我們先創(chuàng)建一個(gè)app目錄:

mkdir app

命名空間是通過(guò)namespace來(lái)聲明的,通過(guò)use關(guān)鍵字來(lái)引入的峰锁。
創(chuàng)建a.php

namespace A;

const NUM = 1;
function output()
{
    echo "A output\n";
}

namespace A2;

const NUM = 2;
function output(){
    echo "A2 output\n";
}

//通過(guò)關(guān)鍵字use來(lái)引入命名空間
use A;
use A2;

echo "NUM from A:" . A\NUM . "\n";
echo "NUM from A2:" . A2\NUM . "\n";
A\output();
A2\output();

運(yùn)行結(jié)果如下:

NUM from A:1
NUM from A2:2
A output
A2 output

上面我們定義了兩個(gè)命名空間萎馅,分別是A和A2,這兩個(gè)命名空間下面有常量NUM虹蒋,函數(shù)output糜芳,是的,故意命名成一模一樣的魄衅,用來(lái)測(cè)試命名空間是否有效峭竣。這個(gè)時(shí)候我們通過(guò)use引入后,A\NUM可以根據(jù)在A命名空間下找到它的NUM晃虫,等于1皆撩,同理A2\NUM等于2,而output函數(shù)也是通過(guò)A\output()傲茄,A2\output()找到各自的函數(shù)毅访,并且輸出各自的內(nèi)容沮榜。

我們初嘗命名空間盘榨,知道用namespace定義命名空間,用use引入命名空間蟆融,通過(guò)命名空間\常量,命名空間\函數(shù)名調(diào)用草巡。

注意:命名空間的定義和文件名乃至目錄結(jié)構(gòu)沒(méi)有任何關(guān)系,比如這里的namespace A完全可以換成namespace Apple型酥,沒(méi)有任何關(guān)系山憨,只要調(diào)用正確即可查乒。

在同一個(gè)文件中聲明不建議采用上述寫(xiě)法,建議用大括號(hào)包起來(lái)郁竟,如下:

<?php
namespace A {
const NUM = 1;
function output()
{
    echo "A output\n";
}
}

namespace A2 {
const NUM = 2;
function output(){
    echo "A2 output\n";
}
}

namespace {
use A;
use A2;

echo "NUM from A:" . A\NUM . "\n";
echo "NUM from A2:" . A2\NUM . "\n";
A\output();
A2\output();
}

以上代碼輸出的結(jié)果和上面是一樣的玛迄,這種寫(xiě)法更佳。

雖然php允許在一個(gè)php文件定義多個(gè)命名空間棚亩,但是違背了“一個(gè)文件定義一個(gè)類(lèi)”的良好實(shí)踐蓖议。一個(gè)文件定義一個(gè)類(lèi),只聲明一個(gè)命名空間讥蟆,這樣更清晰簡(jiǎn)潔勒虾。

在兩個(gè)文件中使用命名空間

創(chuàng)建a.php:

<php
namespace A;

const NUM = 1;

class DB
{
    public function output()
    {
        echo "DB from A\n";
    }
}

創(chuàng)建b.php:

<?php
namespace B;

use A;

const NUM = 2;

class DB
{
    public function output()
    {
        echo "DB from B\n";
    }
}

include "a.php";//必須引入a.php,才能使用a.php中的命名空間
echo "NUM from namespace A:" . A\NUM . "\n";
echo "NUM from namespace B:" . NUM . "\n";

$aObject = new A\DB();
$aObject->output();

$bObject = new DB();
$bObject->output();

然后執(zhí)行b.php文件,輸出如下:

NUM from namespace A:1
NUM from namespace B:2
DB from A
DB from B

這次沒(méi)有使用函數(shù)瘸彤,通過(guò)類(lèi)來(lái)實(shí)踐修然,證明類(lèi)在命名空間下也是有效的。
常量不多說(shuō)质况,它輸出還是正常的愕宋,這里定義了同名的DB類(lèi),但是它們并沒(méi)有沖突结榄,輸出了各自的內(nèi)容掏婶。

有人問(wèn)為什么調(diào)用$bObject = new DB();為什么不需要寫(xiě)成$bObject = new B\DB();,前面為什么不\號(hào)也可以調(diào)用潭陪,因?yàn)槲覀儓?zhí)行的是b.php文件雄妥,當(dāng)前代碼是屬于B這個(gè)命名空間的,默認(rèn)已經(jīng)加上了?依溯。

我們可以嘗試加上\號(hào)老厌,報(bào)錯(cuò)如下:

PHP Fatal error: Uncaught Error: Class 'B\B\DB' not found in b.php

所以,我們?cè)诋?dāng)前命名空間是不需要加\B的黎炉。

全局空間

如果沒(méi)有定義任何命名空間枝秤,所有的類(lèi)與函數(shù)的定義都是在全局空間。在名稱(chēng)前加上前綴 \ 表示該名稱(chēng)是全局空間中的名稱(chēng)慷嗜。

創(chuàng)建comon.php

<?php
function test()
{
    echo "test from common.php\n";
}

創(chuàng)建a.php

<php
namespace A;

function test()
{
    echo "test from a.php\n";
}
include "common.php";
test();   //調(diào)用a.php
\test(); //調(diào)用common.php

執(zhí)行a.php淀弹,結(jié)果下:

test from a.php
test from common.php

其實(shí)php官方把開(kāi)頭帶有\(zhòng)符號(hào)的調(diào)用叫做完全限定名稱(chēng),實(shí)際上就是當(dāng)前整個(gè)作用于有效的庆械,比如上面引入了common.php薇溃,里面有一個(gè)test(),那么就應(yīng)該通過(guò)\test()調(diào)用缭乘。當(dāng)然這是在重名下的調(diào)用沐序,如果common中的test叫做test2,那么可以直接test2();調(diào)用,應(yīng)為在A這個(gè)命名空間下沒(méi)有和它沖突的函數(shù)名策幼。

注意:訪問(wèn)任意全局類(lèi)邑时、函數(shù)或常量,都可以使用完全限定名稱(chēng)特姐,例如 \strlen() 或 \Exception 或 \INI_ALL晶丘。

例如:

<?php
namespace A;

$str = "123";
function strlen($string){
    return \strlen($string) + 1;
}
echo \strlen($str). "\n";
echo strlen($str) . "\n";

輸出結(jié)果:

3
4

顯然當(dāng)前a.php文件中strlen和系統(tǒng)函數(shù)strlen重名了,我們通過(guò)\strlen($str)調(diào)用系統(tǒng)的函數(shù)唐含, strlen($str)是調(diào)用命名空間A的函數(shù)铣口,只不過(guò)它內(nèi)部又是通過(guò)系統(tǒng)函數(shù)strlen實(shí)現(xiàn)的。

命名空間的導(dǎo)入和別名

在我們的實(shí)際項(xiàng)目中遇到的命名空間的層次會(huì)比較深觉壶,比如:

<?php
use App\Component\Net\HttpResponsePostTool;
//這里是偽代碼
$postobject = new HttpResponsePostTool('http://google.com');
$postobject->go();

這個(gè)HttpResponsePostTool很長(zhǎng)脑题,可以用as關(guān)鍵字定義別名:

<?php
use App\Component\Net\HttpResponsePostTool as MyPost;
//這里是偽代碼
$postobject = new MyPost('http://google.com');
$postobject->go();

這樣是否優(yōu)雅很多。

多重導(dǎo)入

雖然良好實(shí)踐是在一個(gè)php文件中做一個(gè)命名空間的聲明铜靶,但是這不妨礙我們導(dǎo)入多個(gè)命名空間叔遂,而且這是經(jīng)常用的。

php允許只使用一次use争剿,通過(guò)逗號(hào)分割命名空間進(jìn)行導(dǎo)入已艰,最后一個(gè)命名空間加上分號(hào),比如:

<?php
use    A,
       B,
       C;

但是不建議這么寫(xiě)蚕苇,不利于閱讀哩掺,最好每行都使用use引入:

<?php
use A;
use B;
use C;

了解以上,基本就能使用命名空間進(jìn)行開(kāi)發(fā)了涩笤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚼吞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹬碧,更是在濱河造成了極大的恐慌舱禽,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件恩沽,死亡現(xiàn)場(chǎng)離奇詭異誊稚,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)罗心,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)里伯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人渤闷,你說(shuō)我怎么就攤上這事疾瓮。” “怎么了肤晓?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵爷贫,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我补憾,道長(zhǎng)漫萄,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任盈匾,我火速辦了婚禮腾务,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘削饵。我一直安慰自己岩瘦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布窿撬。 她就那樣靜靜地躺著启昧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪劈伴。 梳的紋絲不亂的頭發(fā)上密末,一...
    開(kāi)封第一講書(shū)人閱讀 52,246評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音跛璧,去河邊找鬼严里。 笑死,一個(gè)胖子當(dāng)著我的面吹牛追城,可吹牛的內(nèi)容都是我干的刹碾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼座柱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼迷帜!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起色洞,我...
    開(kāi)封第一講書(shū)人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瞬矩,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后锋玲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體景用,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年惭蹂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伞插。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盾碗,死狀恐怖媚污,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情廷雅,我是刑警寧澤耗美,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布京髓,位于F島的核電站,受9級(jí)特大地震影響商架,放射性物質(zhì)發(fā)生泄漏堰怨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一蛇摸、第九天 我趴在偏房一處隱蔽的房頂上張望备图。 院中可真熱鬧,春花似錦赶袄、人聲如沸揽涮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蒋困。三九已至,卻和暖如春敬辣,著一層夾襖步出監(jiān)牢的瞬間家破,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工购岗, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汰聋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓喊积,卻偏偏與公主長(zhǎng)得像烹困,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子乾吻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 提出問(wèn)題 解決問(wèn)題--命名空間的使用 PHP的命名空間(namespace)是php5.3之后才有的髓梅。這個(gè)概念在C...
    洞房花豬閱讀 2,845評(píng)論 0 3
  • 一、php可以做什么 php是一種可以在服務(wù)器端運(yùn)行的編程語(yǔ)言绎签,可以運(yùn)行在Web服務(wù)器端枯饿。 php是一門(mén)后臺(tái)編程語(yǔ)...
    空谷悠閱讀 3,104評(píng)論 4 97
  • 一、 為什么需要命名空間(問(wèn)題提出) 命名空間是ANSIC++引入的可以由用戶(hù)命名的作用域诡必,用來(lái)處理程序中 常見(jiàn)的...
    IvanRunning閱讀 2,364評(píng)論 0 2
  • 作為一種通用開(kāi)源腳本語(yǔ)言奢方,PHP可以在不同的平臺(tái)上運(yùn)行(Windows、LinuxUnix爸舒、MacOS X 等)蟋字,...
    陽(yáng)明先生1208閱讀 950評(píng)論 1 4
  • vector的迭代刪除 map的迭代刪除 vector的這種寫(xiě)法不夠直觀,for循環(huán)中最好不要改變?nèi)萜髅眉t告訴我應(yīng)...
    碎冰op閱讀 833評(píng)論 0 0