上一節我分析了 laravel 的 index 表面,這次我將繼續深入,autoload_real.php 檔案中引入的 loadClassLoader.php 是實現 autoload 的關鍵,這節我也會記錄我對 loadClassLoader.php 的理解。
1.
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
private $missingClasses = array();
private $apcuPrefix;
解讀:初始化 psr0、psr4,以及類 map 陣列
2.
//獲取psr0規範字首
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
//獲取psr4規範字首
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
//獲取psr0規範路徑
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
//獲取psr4規範路徑
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
//獲取類map
public function getClassMap()
{
return $this->classMap;
}
解讀:獲取函式的定義
3.
public function addClassMap(array $classMap)
{
if ($this->classMap) {
//如果該類map存在,則合併,新類map覆蓋舊的
$this->classMap = array_merge($this->classMap, $classMap);
} else {
//如果不存在該map,則加入
$this->classMap = $classMap;
}
}
解讀:類 map 的自載入新增
4.
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
//如果$prefix為空且$prepend為true新增psr0規範檔案回撥路徑,舊的覆蓋新的
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
//如果$prefix為空且$prepend為false天劍psr0規範檔案回撥路徑,新的覆蓋舊的
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
//設定psr0規範檔案字首
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
//如果$prepend為true,舊的psr0規範檔案字首覆蓋新的
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
//如果$prepend為false,新的psr0規範檔案字首覆蓋新的
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
解讀:psr0 規範檔案的自載入新增
5.
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
//為根名稱空間註冊路徑
if ($prepend) {
//如果$prefix為空且$prepend為true新增psr4規範檔案回撥路徑,$this->fallbackDirsPsr4覆蓋$paths
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
//如果$prefix為空且$prepend為true新增psr4規範檔案回撥路徑,新的覆蓋新的
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
//如果尚未設定該psr4規範
// Register directories for a new namespace.
//為新名稱空間註冊路徑
//獲取字首長度
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
//如果字首不是以'\\'結束,丟擲錯誤
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
//獲取psr4規範字首長度
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
//獲取psr4規範字首路徑
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
//如果已經設定該psr4規範
// Prepend directories for an already registered namespace.
//為已經註冊的名稱空間預載入路徑prefixDirsPsr4[$prefix]覆蓋$paths
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
//為已經註冊的名稱空間追加一個路徑
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
解讀:psr4 規範檔案的自載入新增
6.
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
解讀:開啟類檔案包含路徑的搜尋
7.
public function getUseIncludePath()
{
return $this->useIncludePath;
}
解讀:可以用來檢查包含路徑是否已經被自動載入器採用
8.
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
解讀:關掉還沒有註冊 class map 的類字首和回撥路徑的搜尋
9.
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
解讀:判斷是否報搜尋失敗如果沒有在 class map 找到當前類
10.
public function setApcuPrefix($apcuPrefix)
{
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
}
解讀:如果擴充套件是合法的,APCu 字首用來快取 found/not-found 類
11.
public function getApcuPrefix()
{
return $this->apcuPrefix;
}
解讀:如果 APCu 快取不合法,獲取正在使用的,或空的 APCu 字首
12.
public function register($prepend = false)
{
//註冊指定方法為__autoload實現
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
解讀:註冊該例項為一個自動載入器
13.
public function unregister()
{
//從spl中登出autoload
spl_autoload_unregister(array($this, 'loadClass'));
}
解讀:登出指定類例項自動載入器
14.
public function loadClass($class)
{
//如果可以找到該類
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
解讀:載入指定類或介面