tp5.1 Loader自動加載分析(一)

 1、加載流程圖

  1、框架啓動執行 index.php   

// 加載基礎文件
require __DIR__ . '/../thinkphp/base.php';

    2、加載 Loader.php,並執行 register 方法


// 載入Loader類
require __DIR__ . '/library/think/Loader.php';

// 註冊自動加載
Loader::register();
  3、執行 spl_autoload_register函數
 spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);

    4、獲取文件根目錄路徑

  $rootPath = self::getRootPath(); // string(34) "E:\phpStudy\PHPTutorial\WWW\tp5.1\"

  5、獲取 composer文件路徑

self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;

//string(50) "E:\phpStudy\PHPTutorial\WWW\tp5.1\vendor\composer\"

    6、Composer自動加載支持

 

require self::$composerPath . 'autoload_static.php';

 $declaredClass = get_declared_classes();

$composerClass = array_pop($declaredClass);
 // string(68) "Composer\Autoload\ComposerStaticInit2278c8ba0dc45823698bad602102e4b4"

   把 ComposerStaticInit2278c8ba0dc45823698bad602102e4b4 文件中的  $prefixLengthsPsr4 和 $prefixDirsPsr4 兩個屬性分別賦值給 Loader.php 中的 $prefixLengthsPsr4  和 $prefixDirsPsr4

        

 7、註冊命名空間定義

self::addNamespace([
    'think'  => __DIR__,
    'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits',
]);

  

 

addPsr4 方法分析

   

   

var_dump(self::$prefixLengthsPsr4);
        // array(2) {
        //  ["t"]=>
        //  array(3) {
        //    ["think\composer\"]=>
        //    int(15)
        //    ["think\"]=>
        //    int(6)
        //    ["traits\"]=>
        //    int(7)
        //  }
        //  ["a"]=>
        //  array(1) {
        //    ["app\"]=>
        //    int(4)
        //  }
        var_dump(self::$prefixDirsPsr4);
        /**
         * array(4) {
                ["think\composer\"]=>
                array(1) {
                [0]=>
                string(81) "E:\phpStudy\PHPTutorial\WWW\tp5.1\vendor\composer/../topthink/think-installer/src"
                }
                ["app\"]=>
                array(2) {
                [0]=>
                string(45) "E:\phpStudy\PHPTutorial\WWW\tp5.1\application"
                [1]=>
                string(67) "E:\phpStudy\PHPTutorial\WWW\tp5.1\vendor\composer/../../application"
                }
                ["think\"]=>
                array(1) {
                [0]=>
                string(56) "E:\phpStudy\PHPTutorial\WWW\tp5.1\thinkphp\library\think"
                }
                ["traits\"]=>
                array(1) {
                [0]=>
                string(57) "E:\phpStudy\PHPTutorial\WWW\tp5.1\thinkphp\library\traits"
                }
                }
         */

  8、生成類庫映射文件optimize:autoload

php think optimize:autoload

指令執行成功後,會在runtime目錄下面生成classmap.php文件,生成的類庫映射文件會掃描系統目錄和應用目錄的類庫。

   9、自動加載extend目錄

self::addAutoLoadDir($rootPath . 'extend');
// 註冊自動加載類庫目錄
public static function addAutoLoadDir($path)
{
    self::$fallbackDirsPsr4[] = $path;
}

  10、接着在下 執行  Error::register();

Error::register();

   會觸發從第二步註冊 spl_autoload_register 方法,會執行 autoload 方法 

  

  因爲在  self::$classAlias 屬性中不存在 Error 所以會執行下面的  self::findFile($class) 方法

  

 private static function findFile($class)
    {
        if (!empty(self::$classMap[$class])) {
            // 類庫映射
            return self::$classMap[$class];
        }

        // 查找 PSR-4
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
        //var_dump($logicalPathPsr4);die; // string(15) "think\Error.php"

        $first = $class[0]; // t
        if (isset(self::$prefixLengthsPsr4[$first])) {
            //var_dump(self::$prefixLengthsPsr4[$first]);die;
            foreach (self::$prefixLengthsPsr4[$first] as $prefix => $length) {
                if (0 === strpos($class, $prefix)) {
                    foreach (self::$prefixDirsPsr4[$prefix] as $dir) {
                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
                            return $file;
                        }
                    }
                }
            }
        }

   會找到 相應的文件 並返回加載

 

 

總結:通過以上可以瞭解 composer加載的精髓所在及原理

1、可以通過 addNamespace 加載自己擴展的文件

self::addNamespace([
]);

2、通過 addAutoLoadDir 擴展自己的文件。

  self::addAutoLoadDir();

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章