php自動加載規範 PSR4 (Thinkphp)

PSR4是一種自動加載規範,老版本是PSR0,儘管thinkPHP支持PSR4和PSR0的自動加載方式,可是默認也是優先進行PSR4加載,若是失敗,再進行PSR0的加載。本篇文章只會討論PSR4的加載。php

 

代碼示例:linux

spl_autoload_register(function ($class) { // 指定項目的命名空間前綴 $prefix = 'Foo\\Bar\\'; // 指定項目的根目錄 $base_dir = __DIR__ . '/src/'; // 判斷類的前綴是否是上面的命名空間前綴 $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // 不是,則交給其餘類加載器去加載,不使用PSR4 return; } // 獲取相對的命名空間 $relative_class = substr($class, $len); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php // 使用根目錄替換命名空間前綴,使用目錄分隔符替換相對類名中的命名空間分隔符,而後再加上.php $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // 若是該類存在,則require它 if (file_exists($file)) { require $file; } });

從上面的代碼中,咱們就能夠知道PSR4究竟是幹什麼的。
這個規範主要就是將類轉換成物理路徑。thinkphp

  1. 命名空間前綴使用根目錄替換
  2. 去掉命名空間前綴剩下的部分,叫作它相對類名
  3. 使用目錄分隔符替換掉相對類名中的命名空間分隔符(也就是\變成/)
  4. 加上.php

好比thinkphp典型的一個控制器:Index.phpwindows

<?php namespace app\index\controller; class Index{ } 

那麼在加載的時候,傳給這個PSR4的時候,$class=app\index\controller\Index;數組

假設當前的根目錄爲:E:\app
當前的命名空間前綴爲:app
根據前面的轉換步驟,這個類的路徑應該是在:
E:/app/index/controller/Index.phpapp

路徑的斜杆(/)跟反斜杆(\)。在windows中一般是使用反斜杆做爲路徑分隔符的,而在linux中,經過是使用斜杆做爲路徑分隔符的。不過windows如今的API都支持使用斜杆做爲路徑分隔符了,而若是使用反斜杆的話,那麼在單引號中,還須要寫成\才能當成\。而linux中是使用/,所以咱們的路徑表示即是使用斜杆了。composer

有同窗跟我反映說,php單引號不是不會被轉義嗎?這個確實是,不過對於要輸出單引號,所以在單引號字符串中,單引號是須要使用反斜杆轉義才能輸出的,而反斜杆自己也是須要使用反斜杆來轉義,對於其餘的轉義,就真的不會了。框架

thinkphp5的類加載

類庫映射實際上就是保存一個鍵值對數組,鍵值爲類名,值爲物理路徑,這樣當類加載的時候,直接查找該數組就行。thinkphp5

而對於PSR4,咱們根據上面知道,須要註冊根目錄跟命名空間前綴。
在thinkphp中註冊了五個命名空間前綴:ui

self::addNamespace([ 'think' => LIB_PATH . 'think' . DS, 'behavior' => LIB_PATH . 'behavior' . DS, 'traits' => LIB_PATH . 'traits' . DS, ]); 

還有兩個是能夠配置的:

self::$namespace = $config['app_namespace']; Loader::addNamespace($config['app_namespace'], APP_PATH); if (!empty($config['root_namespace'])) { Loader::addNamespace($config['root_namespace']); } 

所以在配置文件中的app_namespace就是指明應用的命名空間前綴。好比默認爲app對應着跟目錄爲application。

PSR4的備選目錄

當使用PSR4方式讀取失敗的話,那麼還有備選的目錄能夠用來讀取,thinkphp即是使用這種方式做爲擴展目錄的讀取:

// 查找 PSR-4 fallback dirs foreach (self::$fallbackDirsPsr4 as $dir) { if (is_file($file = $dir . DS . $logicalPathPsr4)) { return $file; } } 

$logicalPathPsr4就是這事將命名空間分隔符轉換爲目錄分隔符再加上.php而已。

不過,一般來講,開源的擴展應該使用composer開發。而只有私人的擴展,通常才放在extend目錄下的。

爲何TP不徹底使用composer的加載器呢?
一是徹底基於composer的話,那麼當composer更新的時候,框架也須要相對應地調整,所以不可以徹底地專一於框架的開發。二若是徹底拋棄composer而專一於框架,又像是撿了芝麻丟了西瓜。所以將composer做爲框架的延伸擴展,無疑是一種比較好的折中方案。

原文連接:https://www.kancloud.cn/code7/tp5/343057
相關文章
相關標籤/搜索