目錄
- 名稱空間
- 概念?解決了什麼問題?
- 定義
- 使用和解析規則
- 其他
- 自動載入
- 概念?解決了什麼問題?
- PSR-4
名稱空間
概念
名稱空間是類似於檔案系統的一個虛擬容器,可以用於類(包括抽象類和traits)、介面、函式、常量。
類似於檔案系統,可以把類放進一個多層級的名稱空間,主要是解決類名的命名衝突問題。
定義名稱空間
<?php
namespace haha\hehe\heihei
const CON1 = 10;
function run(){
//....
}
class ClassA{
//....
}
- 用namespace宣告一個名稱空間,表明接下去的程式碼屬於這個名稱空間
- 宣告語句必須是檔案第一句
- 也可以在後面加個大括號來顯式表明這個名稱空間範圍,這樣可以做到一個檔案中有多個名稱空間,但是非常不建議這樣,沒必要,沒有可讀性,一般就是這樣使用,也不用大括號
複製程式碼
使用名稱空間
沒有名稱空間之前,就是
require('\src\ClassA.php');
new ClassA();
複製程式碼
有了名稱空間後
//現在都配合自動載入,不require
new \haha\hehe\heihei\ClassA();
複製程式碼
如果多次要new一個物件,覺得累贅,可以這樣
use haha\hehe\heihei\ClassA; //注意最前面的斜槓可以省略
$obj1 = new ClassA();
$obj2 = new ClassA();
$obj3 = new ClassA();
複製程式碼
這叫匯入類,還可以給類起別名
use haha\hehe\heihei\ClassA as A; //注意最前面的斜槓可以省略
new A();
複製程式碼
命名解析規則
- 解析名稱空間跟檔案系統的路徑解析是一樣的,有相對路徑和絕對路徑兩種。
- 絕對路徑在名稱空間中叫“完全限定名”,檔案系統的根目錄是\,名稱空間也是\,以\開頭的就是完全限定名
- 相對路徑在名稱空間叫“非限定名”(只有類名),“限定名”(有路徑,但是不是從\開始),總之不是\開頭的
- 絕對路徑(完全限定名)的解析沒啥的,都從\開始,明明白白
- 非完全限定的,解析的時候就會加上當前名稱空間名稱
<?php
namespace My\n1amespace
new \app\controller\User(); //完全限定名 很清楚
new User(); //就解析為My\n1amespace\User
new haha\User(); //就解析為My\n1amespace\haha\User
複製程式碼
其他
__NAMESPACE__常量
<?php
namespace My\n1amespace{
echo 'inside'.__NAMESPACE__; //My\n1amespace 如果沒有名稱空間就是''
}
複製程式碼
自動載入
概念
如果你需要用一個類,那你得先require,當你用一個類的時候,可能無所謂,當你的類用的多的時候,就很麻煩了。
自動載入1.0,在名稱空間出現之前,就有自動載入,與原理就是,你可以告訴php直譯器一個函式(用__autoload()或者spl_autoload_register()註冊
),當你用一個類,而又沒有匯入的時候,系統就會執行這個函式。
自動載入2.0,在名稱空間出現後,PSR-4規定了一個基於名稱空間的統一的自動載入規範
PSR-4
其實問題的核心是,如何從名稱空間,得到實際的檔案位置?
兩點
- 通過自動載入函式 將根名稱空間或者較高階別的名稱空間 與 目錄一一關聯
- 從根目錄或者特定的目錄往下,命名層級與目錄層級一一對應
看一個例子就知道
spl_autoload_register(function($class_name){
//名稱空間字首
$prefixe = '\Foo\\Bar';
//基目錄
$base_dir = __DIR__.'/src/';
//匹配是否 是在尋找這個名稱空間下的類
$len = strlen($prefix);
if(strncmp($prefix,$class_name,$len)!==0){
return ;
}
//將名稱空間轉換為目錄位置
$relative_class = substr($class.$len);
$file = $base_dir . str_replace('\\','/',$relative_class).'.php';
if(file)existst($file)){
require($file);
}
})
複製程式碼
參考資料
- php手冊
- modern PHP 對應章節