PHP命名空間和公共空間

PHP命名空間

PHP 命名空間(namespace)是在PHP 5.3中加入的瞭亮。
PHP 命名空間可以解決以下兩類問題:

  1. 用戶編寫的代碼與PHP內(nèi)部的類/函數(shù)/常量或第三方類/函數(shù)/常量之間的名字沖突县爬。
  2. 為很長的標(biāo)識符名稱(通常是為了緩解第一類問題而定義的)創(chuàng)建一個別名(或簡短)的名稱晌坤,提高源代碼的可讀性敦冬。

php手冊:命名空間概述

定義命名空間

默認(rèn)情況下庶喜,所有常量、類和函數(shù)名都放在全局空間下揍庄,就和PHP支持命名空間之前一樣咆蒿。

命名空間通過關(guān)鍵字namespace 來聲明。如果一個文件中包含命名空間蚂子,它必須在其它所有代碼之前聲明命名空間沃测。語法格式如下:

<?php  
// 定義代碼在 'MyProject' 命名空間中  
namespace MyProject;  
 
// ... 代碼 ...
?>

也可以在同一個文件中定義不同的命名空間代碼,如:

<?php  
namespace MyProject;

const CONNECT_OK = 1; //命名空間對const變量管用
class Connection { /* ... */ } //對類管用
function connect() { /* ... */  } //同樣對函數(shù)管用

namespace AnotherProject;

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

但是食茎,命名空間對define定義的常量不管用:

<?php
namespace one;
    define('value1', 'value2');

namespace two;
    define('value1', 'value3');
?>

就會報(bào)錯:

Notice: Constant value1 already defined in A:\myphp_www\PHPTutorial\WWW\tp5\test.php on line 19
  • 注意事項(xiàng):
  1. 聲明命名空間之前唯一合法的代碼是用于定義源文件編碼方式的 declare語句蒂破。所有非 PHP 代碼包括空白符都不能出現(xiàn)在命名空間的聲明之前。
<?php
declare(encoding='UTF-8'); //定義多個命名空間和不包含在命名空間中的代碼
namespace MyProject {

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

namespace { // 全局代碼
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

以下代碼會出現(xiàn)語法錯誤:

<html>
<?php
namespace MyProject; // 命名空間前出現(xiàn)了“<html>” 會致命錯誤 - 命名空間必須是程序腳本的第一條語句
?>

就會出現(xiàn)致命錯誤:

Fatal error: Namespace declaration statement has to be the very first statement in the script in
A:\myphp_www\PHPTutorial\WWW\tp5\test.php on line 23
  1. 將全局的非命名空間中的代碼與命名空間中的代碼組合在一起别渔,只能使用大括號形式的語法附迷。全局代碼必須用一個不帶名稱的namespace 語句加上大括號括起來。
<?php
namespace MyProject { //命名空間代碼

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

namespace { // 全局代碼
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

子命名空間

與目錄和文件的關(guān)系很像哎媚,PHP 命名空間也允許指定層次化的命名空間的名稱喇伯。因此,命名空間的名字可以使用分層次的方式定義:

<?php
namespace MyProject\Sub\Level;  //聲明分層次的單個命名空間

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

?>

上面的例子創(chuàng)建了常量MyProject\Sub\Level\CONNECT_OK拨与,類 MyProject\Sub\Level\Connection 和函數(shù) MyProject\Sub\Level\Connect稻据。

命名空間使用

PHP 命名空間中的類名可以通過三種方式引用:

  1. 非限定名稱,或不包含前綴的類名稱买喧,即訪問的是當(dāng)前命名空間里的內(nèi)容捻悯。例如$a=new foo();foo::staticmethod();匆赃。如果當(dāng)前命名空間是 currentnamespacefoo 將被解析為currentnamespace\foo今缚。如果使用 foo 的代碼是全局的算柳,不包含在任何命名空間中的代碼,則foo 會被解析為foo荚斯。 警告:如果命名空間中的函數(shù)或常量未定義埠居,則該非限定的函數(shù)名稱或常量名稱會被解析為全局函數(shù)名稱或常量名稱。

  2. 限定名稱事期,或包含前綴的名稱滥壕,以當(dāng)前命名空間所處的路徑為相對路徑,繼續(xù)向下尋找指定的命名空間兽泣,類似于文件相對路徑绎橘。例如$a = new subnamespace\foo();subnamespace\foo::staticmethod();。如果當(dāng)前的命名空間是currentnamespace唠倦,則 foo 會被解析為currentnamespace\subnamespace\foo称鳞。如果使用foo的代碼是全局的,不包含在任何命名空間中的代碼稠鼻,foo 會被解析為subnamespace\foo冈止。

  3. 完全限定名稱,或包含了全局前綴操作符的名稱候齿,和文件絕對路徑(根目錄)的訪問方式相似熙暴。例如, $a = new \currentnamespace\foo();\currentnamespace\foo::staticmethod();慌盯。在這種情況下周霉,foo總是被解析為代碼中的文字名(literal name)currentnamespace\foo

  • file1.php
<?php
namespace Foo\Bar\subnamespace; //子命名空間

const FOO = 1;
function foo() {}
class foo
{
    static function staticmethod() {}
}
?>
  • file2.php
<?php
namespace Foo\Bar;
include 'file1.php';//引入file.php文件

const FOO = 2;
function foo() {}
class foo
{
    static function staticmethod() {}
}

/* 非限定名稱 */
foo(); // 解析為函數(shù) Foo\Bar\foo
foo::staticmethod(); // 解析為類 Foo\Bar\foo 亚皂,方法為 staticmethod
echo FOO; // 解析為常量 Foo\Bar\FOO

/* 限定名稱 */
subnamespace\foo(); // 解析為函數(shù) Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // 解析為類 Foo\Bar\subnamespace\foo,
                                  // 以及類的方法 staticmethod
echo subnamespace\FOO; // 解析為常量 Foo\Bar\subnamespace\FOO
                                  
/* 完全限定名稱 */
\Foo\Bar\foo(); // 解析為函數(shù) Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // 解析為類 Foo\Bar\foo, 以及類的方法 staticmethod
echo \Foo\Bar\FOO; // 解析為常量 Foo\Bar\FOO
?>

注意:訪問任意全局類俱箱、函數(shù)或常量,都可以使用完全限定名稱灭必,例如 \strlen()\Exception\INI_ALL狞谱。
在命名空間內(nèi)部訪問全局類、函數(shù)和常量:

<?php
namespace Foo;

function strlen() {}
const INI_ALL = 3;
class Exception {}

$a = \strlen('hi'); // 調(diào)用全局函數(shù)strlen
$b = \INI_ALL; // 訪問全局常量 INI_ALL
$c = new \Exception('error'); // 實(shí)例化全局類 Exception
?>

引入空間成員

  1. use 空間名\空間名 【as 別名】:將指定空間引入到當(dāng)前空間禁漓。同可以使用as關(guān)鍵字為被引入的空間起個別名跟衅。

  2. use 空間名\空間名\成員類 【as別名】:將指定的空間中的成員引入到當(dāng)前空間,引入空間成員只能引入類璃饱。

<?php
namespace foo;
use My\Full\Classname as Another;

// 下面的例子與 use My\Full\NSname as NSname 相同
use My\Full\NSname;

// 導(dǎo)入一個全局類
use \ArrayObject;

$obj = new namespace\Another; // 實(shí)例化 foo\Another 對象
$obj = new Another; // 實(shí)例化 My\Full\Classname 對象
NSname\subns\func(); // 調(diào)用函數(shù) My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // 實(shí)例化 ArrayObject 對象
// 如果不使用 "use \ArrayObject" 与斤,則實(shí)例化一個 foo\ArrayObject 對象
?>

一行包含多個use語句情況:

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 實(shí)例化 My\Full\Classname 對象
NSname\subns\func(); // 調(diào)用函數(shù) My\Full\NSname\subns\func
?>

導(dǎo)入操作是在編譯執(zhí)行的肪康,但動態(tài)的類名稱荚恶、函數(shù)名稱或常量名稱則不是撩穿。

  1. 導(dǎo)入和動態(tài)名稱
<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 實(shí)例化一個 My\Full\Classname 對象
$a = 'Another';
$obj = new $a;      // 實(shí)際化一個 Another 對象
?>

另外,導(dǎo)入操作只影響非限定名稱和限定名稱谒撼。完全限定名稱由于是確定的食寡,故不受導(dǎo)入的影響。

  1. 導(dǎo)入和完全限定名稱
<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // 實(shí)例化 My\Full\Classname 類
$obj = new \Another; // 實(shí)例化 Another 類
$obj = new Another\thing; // 實(shí)例化 My\Full\Classname\thing 類
$obj = new \Another\thing; // 實(shí)例化 Another\thing 類
?>

PHP公共空間

可以簡單的理解廓潜,沒有定義命名空間的方法(函數(shù))抵皱、類庫(class)、屬性(變量)都默認(rèn)歸屬于公共空間辩蛋。這樣就解釋了為php5.3.0以前版本書寫的代碼大部分為何在php5.3.0及其以上版本還能正常運(yùn)行的原因呻畸。
另外:公共空間中的代碼段被引入到某個命名空間下后,該公共空間中的代碼段不屬于任何命名空間悼院!

  • 1.php
<?php

 function fun(){  

 }

 class Demo{

 }
?>
  • 2.php
<?php
 namespace cn\my;
 include 'common.php';  //引入當(dāng)前目錄下的文件
 $demo = new Demo;    //出現(xiàn)致命錯誤:找不到 cn\my\Demo類
 $demo = new \Demo(); //正確的方式  加上 \
 var_dump();   // 錯誤伤为,系統(tǒng)函數(shù)在公共空間
 \var_dump();  // 正確,使用了 \
?>

說明:調(diào)用公共空間的方式是直接在元素名稱前面加上 \就可以了据途,否則 PHP 解析器會認(rèn)為用戶像調(diào)用當(dāng)前空間下的元素绞愚。除了自定義的元素,還包括 PHP 自帶的元素颖医,都屬于公共空間位衩。其實(shí)公共空間的函數(shù)和常量不用加\ 也可以正常調(diào)用,但是為了正確區(qū)分元素所在區(qū)域熔萧,還是建議調(diào)用函數(shù)的時候加上\ 糖驴。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市哪痰,隨后出現(xiàn)的幾起案子遂赠,更是在濱河造成了極大的恐慌,老刑警劉巖晌杰,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跷睦,死亡現(xiàn)場離奇詭異,居然都是意外死亡肋演,警方通過查閱死者的電腦和手機(jī)抑诸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爹殊,“玉大人蜕乡,你說我怎么就攤上這事」?洌” “怎么了层玲?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我辛块,道長畔派,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任润绵,我火速辦了婚禮线椰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘尘盼。我一直安慰自己憨愉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布卿捎。 她就那樣靜靜地躺著配紫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪午阵。 梳的紋絲不亂的頭發(fā)上笨蚁,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機(jī)與錄音趟庄,去河邊找鬼括细。 笑死,一個胖子當(dāng)著我的面吹牛戚啥,可吹牛的內(nèi)容都是我干的奋单。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼猫十,長吁一口氣:“原來是場噩夢啊……” “哼览濒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拖云,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贷笛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宙项,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乏苦,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年尤筐,在試婚紗的時候發(fā)現(xiàn)自己被綠了汇荐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盆繁,死狀恐怖掀淘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情油昂,我是刑警寧澤革娄,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布倾贰,位于F島的核電站,受9級特大地震影響拦惋,放射性物質(zhì)發(fā)生泄漏躁染。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一架忌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧我衬,春花似錦叹放、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至破加,卻和暖如春俱恶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背范舀。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工合是, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锭环。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓聪全,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辅辩。 傳聞我的和親對象是個殘疾皇子难礼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355