命名空間其實(shí)早在PHP5.3就已經(jīng)出現(xiàn)了。不過(guò)大部分同學(xué)可能在各種框架的使用中才會(huì)接觸到命名空間的內(nèi)容,當(dāng)然,現(xiàn)代化的開發(fā)也都離不開這些能夠快速產(chǎn)出的框架。
首先,我們要定義命名空間是個(gè)什么東西。
其實(shí)就像操作系統(tǒng)的目錄一樣,命名空間就是為了解決類似于操作系統(tǒng)中同一個(gè)文件夾不能有相同的文件名一樣的問(wèn)題。假設(shè)我們只有一個(gè)文件,一個(gè)目錄,那么在這個(gè)目錄中,是不能有兩個(gè)完全相同的文件的。如果有這樣名稱完全相同的文件,那么操作系統(tǒng)也不知道我們到底應(yīng)該打開的是哪一個(gè)文件。同理,在一個(gè)PHP文件中,我們也不能起相同名稱的函數(shù)或者類名,PHP也不知道我們到底要調(diào)用的是哪一個(gè)函數(shù)或者類。
理解了上述內(nèi)容之后,再來(lái)看命名空間的語(yǔ)法,其實(shí)非常像我們的目錄的定義。
namespace A\B\C;
這個(gè)命名空間的定義就是指出了當(dāng)前命名空間是A\B\C。就像是C:\A\B\C這樣一個(gè)文件夾一樣。光說(shuō)不練假把式,直接上代碼來(lái)看看:
// file1.php namespace FILE1; const CONST_A = 2; function testA(){ echo 'FILE1\testA()', PHP_EOL; } class objectA{ function test(){ echo 'FILE1\ObjectA', PHP_EOL; } }
// file2.php namespace FILE2; const CONST_A = 3; function testA(){ echo 'FILE2\testA()', PHP_EOL; } class objectA{ function test(){ echo 'FILE2\ObjectA', PHP_EOL; } }
我們?cè)趎amespace目錄下創(chuàng)建了這兩個(gè)php文件,函數(shù)和類名都是一樣的,但定義了不同的命名空間,一個(gè)是FILE1,一個(gè)是FILE2。
namespace A; include 'namespace/file1.php'; include 'namespace/file2.php'; use FILE1, FILE2; use FILE1\objectA as objectB; const CONST_A = 1; function testA(){ echo 'A\testA()', PHP_EOL; } class objectA{ function test(){ echo 'A\ObjectA', PHP_EOL; } } // 當(dāng)前命名空間 echo CONST_A, PHP_EOL; // 1 testA(); // A\testA() $oA = new objectA(); $oA->test(); // A\ObjectA // FILE1 echo FILE1\CONST_A, PHP_EOL; // 2 FILE1\testA(); // FILE1\testA() $oA = new FILE1\objectA(); $oA->test(); // FILE1\ObjectA $oB = new objectB(); $oB->test(); // FILE1\ObjectA // FILE2 echo FILE2\CONST_A, PHP_EOL; // 3 FILE2\testA(); // FILE2\testA() $oA = new FILE2\objectA(); $oA->test(); // FILE2\ObjectA
在測(cè)試代碼中,我們又定義了當(dāng)前的命名空間為A。并include了file1.php和file2.php。并在這個(gè)文件中同時(shí)也定義了與file1.php和file2.php中相同的函數(shù)和類名。接下來(lái)我們依次調(diào)用這些靜態(tài)變量、函數(shù)和類。
- 在默認(rèn)情況下,靜態(tài)變量、函數(shù)、類調(diào)用的是當(dāng)前命名空間下的內(nèi)容
- 在使用了FILE1\和FILE2\之后,調(diào)用的是就是指定命名空間下的內(nèi)容
- 需要使用use引入命名空間,否則無(wú)法使用命名空間里的內(nèi)容
- use中可以使用as關(guān)鍵字為命名空間或者其中的類指定別名
命名空間的使用其實(shí)就是這么的簡(jiǎn)單??梢钥闯鑫覀?cè)诓煌拿臻g中就可以使用相同的函數(shù)或者類名了。這一點(diǎn)正是各類現(xiàn)代化開發(fā)框架的基礎(chǔ)。同時(shí)也是composer能夠?qū)崿F(xiàn)的最主要的原因之一。
接下來(lái),我們嘗試一個(gè)問(wèn)題是否符合我們的預(yù)期,那就是兩個(gè)文件定義相同的命名空間是否能夠定義相同的類名呢?
// file1-1.php namespace FILE1; const CONST_A = 1.1; function testA(){ echo 'FILE1-1\testA()', PHP_EOL; } class objectA{ function test(){ echo 'FILE1-1\ObjectA', PHP_EOL; } }
我們定義了一個(gè)file1-1.php,并且使用了和file1.php相同的FILE1命名空間。然后和file1.php一起include到測(cè)試代碼中。
include 'namespace/file1.php'; include 'namespace/file1-1.php'; // Cannot redeclare FILE1\testA()
好吧,在運(yùn)行時(shí)直接就報(bào)錯(cuò),不能重復(fù)定義同名的函數(shù)名。如果注釋掉函數(shù),那么會(huì)繼續(xù)報(bào)類名不能重復(fù)。我們?cè)俣x一個(gè)file1-2.php,這次還是使用FILE1這個(gè)命名空間,但是內(nèi)容不一樣了。
// file1-2.php namespace FILE1; const CONST_A = 1.2; function testA1_2(){ echo 'FILE1-2\testA()', PHP_EOL; } class objectA1_2{ function test(){ echo 'FILE1-2\ObjectA', PHP_EOL; } }
這樣當(dāng)然就沒(méi)問(wèn)題啦。這兩個(gè)文件在同一個(gè)命名空間下,但是卻有著不同的能力,這樣是完全OK的操作。
include 'namespace/file1.php'; include 'namespace/file1-2.php'; use FILE1; // FILE1 echo FILE1\CONST_A, PHP_EOL; // 2 FILE1\testA(); // FILE1\testA() $oA = new FILE1\objectA(); $oA->test(); // FILE1\ObjectA // FILE1_2 echo FILE1\CONST_A, PHP_EOL; // 3 FILE1\testA1_2(); // FILE1-2\testA() $oA = new FILE1\objectA1_2(); $oA->test(); // FILE1-2\ObjectA