namespace命名空間介紹
定義:
主要是用於解決相同 class 名稱的問題,如果有兩個人寫了相同名稱的類別,一旦同時載入就會有衝突,而 namespace 就是為了解決這個問題,使多人開發時不會被名稱所限制。
宣告與使用:
<php
namespace TextExample; class HelloWorld
{ ...
}?>
在 php 程式的開頭第一行,需要先宣告,若是第一行沒有宣告會有錯誤訊息,也要注意不可將宣告放在 class、function 中,同時避免宣告名字會被使用(通常以組織或公司名字當代表),而接下來的 function 與 class 都會冠上一層名稱像是 TestExample\Helloworld 這樣。
備註:
1.習慣上於將第一個命名為開發者,第二為該相對應的功能,第三或更多層表示class。ex:(namspace Michael\Blog\Search , namespace Michael\Blog\Media)
2.namespace的宣告建議遵守一個文件一個的習慣, 不建議同一個文件中出現多個命名空間。
<?php namespace TestExample;use VeryBuy/Tech as Tech;use VeryBuy\Founder as Founderclass HelloWorld extends Founder{…}?>
Use關鍵字
在宣告完成後會直接在下面使用 use ,把其他也會用到 namespace 下的 class 一起引用進來以方便使用。
As關鍵字
有時 namespace 下的名稱可能會很長包含很多層,導致下面呼叫使用時容易出錯,這時可以使用 as 關鍵字,一來可以方便他人與自己一目瞭然的識別,二來也可以縮短程式碼減少出錯率。
備註:
1.在使用use時可以一次匯入多個 namespacec 或類別,但是不建議這麼做,最好的方式還是一個一個匯入。ex:( use VeryBuy\Tech , VeryBuy\Founder ; 等同於 use VeryBuy\Tech ; VeryBuy\Founder ;)
簡單幾個例子
1.
// Hello.php
<?php
namespace Test\Hello;
class SayWhat
{
public function say()
{
return "Hello"; }}
?>//Hi.php
<?php
namespace Test\Hi;
class SayWhat
{
public function say()
{
return "Hi";}}?>//SaySomething.php
<?php
include "Hello.php";
include "Hi.php";$obj = new Test\Hello\SayWhat();
echo $obj->say(); // Hello
$obj2 = new Test\Hi\SayWhat();
echo $obj2->say(); // Hi?>
先個別在Hello.php中宣告命名空間為 Hello、Hi.php 中宣告命名宣告為 Hi,且都有一個都有一個 say 的函式,並且在 SaySomeThing.php 中先引入兩隻檔案(27.28行),並在下面使用 say 函式(32.34),雖然都是用同個 class 名稱的function,但在new時指定他們,就能印出相對應的 Hello 以及 Hi
2.
<?php
require_once "Test.php";
use Michael\Test;echo $a; // 0
echo CON; // 10// 如果要呼叫function或class時
echo Test\get(); // 1
$obj = new Test\Example();
$obj->set(1, 2, 3);
$obj->call(); // 1,2,3?>// Test.php
<?php
namespace Michael\Test;$a = 0;
define("CON", 10);function get()
{
return 1;
}class Example
{
public $var;
protected $var2;
private $var3; public function set($var, $var2, $var3)
{
$this->var = $var;
$this->var2 = $var2;
$this->var3 = $var3; } public function call()
{
echo $this->var . "," . $this->var2 . "," . $this->var3; }}?>
1.在 namespace下的常數與變數可以直接使用(5,6行),但是 function 和 class無法直接使用。
2.或是在上方直接使用 use (ex:use Michael\Test\Example)等等
命名空間解析的規則:
先介紹三種名稱、分別是非限定、限定以及完全限定名稱。
$a = new Test();
Test::staticmethod();$b = new subnamespace\Test();
subnamespace\Test::staticmethod();$c = \currentnamespace\Test();
\currentnamespace\Test::staticmethod();
1.非限定名稱( Unqualified name ):不包含 namespace 以及分隔符號的關鍵字。
2.限定名稱( Qualified name ):名稱中含有 namespace 以及分隔符號,但開頭不是分隔號。
3.完全限定名稱( Fully qualified name ): 名稱中含有 namespace 以及分隔符號,且開頭是分隔號的。
解析規則
1.非限定名稱、限定名稱會根據當前的匯入在編譯時進行轉換。
ex:如果 namspace A\B\C 匯入 C 時,呼叫 C\D\e() 時,會轉換成A\B\C\D\e()。
2.在 namespace 之下只要沒有經過規則轉換的限定名稱都會自動加上當前的 namespace 名稱。
ex:在 namespace A\B 內呼叫 C\D\e() 來使用,會自動加上 A\B namespace 變成 A\B\C\D\e()。
3.非限定名稱根據當前匯入規則在編譯時轉換。
ex: namespace A\B\C 匯入 C 時,new C() 就代表 new A\B\C()。
4.在 A\B namespace 下呼叫非限定名稱的函式時,
(a). 在當前的 namespace 下尋找 A\B\Test() 函式。
(b). 在全域的空間呼叫 Test() 函式來用。
結論
- namespace 就像在把 class 加上書籤重新再分類一次好幫助辨別。
- 一個檔案或是一個 class 最好使用一個 namespace 就好,避免不易閱讀。
- use 關鍵字必須包含完整的路徑加上class