我獨自走進 Laravel5.5 的❤(二)

姚志博發表於2018-03-28

上一節我分析了 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;
    }
}

解讀:載入指定類或介面

相關文章