PHP命名空間與PSR-4自動加載

目錄php

  • 命名空間
    • 概念?解決了什麼問題?
    • 定義
    • 使用和解析規則
    • 其餘
  • 自動加載
    • 概念?解決了什麼問題?
    • PSR-4

命名空間

概念

命名空間是相似於文件系統的一個虛擬容器,能夠用於類(包括抽象類和traits)、接口、函數、常量。bash

相似於文件系統,能夠把類放進一個多層級的命名空間,主要是解決類名的命名衝突問題。app

定義命名空間

<?php
namespace haha\hehe\heihei
const CON1 = 10;
function run(){
 //....   
}
class ClassA{
 //....   
}

- 用namespace聲明一個命名空間,代表接下去的代碼屬於這個命名空間
- 聲明語句必須是文件第一句
- 也能夠在後面加個大括號來顯式代表這個命名空間範圍,這樣能夠作到一個文件中有多個命名空間,可是很是不建議這樣,不必,沒有可讀性,通常就是這樣使用,也不用大括號


複製代碼

使用命名空間

沒有命名空間以前,就是ide

require('\src\ClassA.php'); 
new ClassA();
複製代碼

有了命名空間後函數

//如今都配合自動加載,不require
new \haha\hehe\heihei\ClassA();
複製代碼

若是屢次要new一個對象,以爲累贅,能夠這樣ui

use haha\hehe\heihei\ClassA; //注意最前面的斜槓能夠省略
$obj1 = new ClassA();
$obj2 = new ClassA();
$obj3 = new ClassA();
複製代碼

這叫導入類,還能夠給類起別名spa

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__常量code

<?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);
    }
})
複製代碼

參考資料


  1. php手冊
  2. modern PHP 對應章節
相關文章
相關標籤/搜索