第1節 自動加載Loader深度分析

1.入口文件/public/index.php

在這裏插入圖片描述

2.加載框架引導文件/thinkphp/start.php

在這裏插入圖片描述

3. 引入基礎文件 /thinkphp/bash.php

  • 定義環境常量
  • 載入Loader類(下文着重記錄Loader)
  • 加載環境變量配置文件.env
  • 註冊自動加載
  • 註冊錯誤和異常處理機制
  • 加載慣例配置文件(就是框架自身的配置文件)
define('THINK_VERSION', '5.0.24');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
define('LIB_PATH', THINK_PATH . 'library' . DS);
define('CORE_PATH', LIB_PATH . 'think' . DS);
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目錄
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件後綴
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 環境變量的配置前綴

// 環境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);


// 載入Loader類
require CORE_PATH . 'Loader.php';
 
// 加載環境變量配置文件
if (is_file(ROOT_PATH . '.env')) {
    $env = parse_ini_file(ROOT_PATH . '.env', true);

    foreach ($env as $key => $val) {
        $name = ENV_PREFIX . strtoupper($key);

        if (is_array($val)) {
            foreach ($val as $k => $v) {
                $item = $name . '_' . strtoupper($k);
                putenv("$item=$v");
            }
        } else {
            putenv("$name=$val");
        }
    }
}

// 註冊自動加載
\think\Loader::register();

// 註冊錯誤和異常處理機制
\think\Error::register();

// 加載慣例配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

4. 引入Loader類 \thinkphp\library\think\Loader.php,調用register方法

  • sql_autoload_register
    • 1:__autoload($class) 因爲是一個函數,所以只能定義一次,使用多個會衝突報錯;而 sql_autoload_register(‘function’) 可定義多個,它有效地創建一個隊列的自動裝載函數並按順序依次定義

    • 2:SPL函數很豐富,有更多的操作空間:如spl_autoload_unregister()註銷已經註冊的函數、spl_autoload_functions()返回所有已經註冊的函數等

    /**
     * 註冊自動加載機制
     * @access public
     * @param  callable $autoload 自動加載處理方法
     * @return void
     */
    public static function register($autoload = null)
    {
        // 註冊系統自動加載 (當調用的類找不到時,自動調用Loader::autoload方法加載找不到的類)
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
        // Composer 自動加載支持
        if (is_dir(VENDOR_PATH . 'composer')) {
            if (PHP_VERSION_ID >= 50600 && is_file(VENDOR_PATH . 'composer' . DS . 'autoload_static.php')) {
                require VENDOR_PATH . 'composer' . DS . 'autoload_static.php';

                $declaredClass = get_declared_classes(); // 返回由當前腳本中已定義類的名字組成的數組(包括內置類和自定義的類)。
                
                $composerClass = array_pop($declaredClass);
                
                // 把composer類中的屬性賦予給Loader類
                foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
                    if (property_exists($composerClass, $attr)) { // 檢測該類或對象是否有該屬性
                        self::${$attr} = $composerClass::${$attr};
                    }
                }
            } else {
                self::registerComposerLoader();
            }
        }

        // 註冊命名空間定義
        self::addNamespace([
            'think'    => LIB_PATH . 'think' . DS,
            'behavior' => LIB_PATH . 'behavior' . DS,
            'traits'   => LIB_PATH . 'traits' . DS,
        ]);

        // 加載類庫映射文件 執行命令php think optimize:autoload 生成/runtime/classmap.php文件
        if (is_file(RUNTIME_PATH . 'classmap' . EXT)) {
            self::addClassMap(__include_file(RUNTIME_PATH . 'classmap' . EXT));
        }

        self::loadComposerAutoloadFiles();

        // 自動加載 extend 目錄,也可以在根目錄下創建文件夾,然後添加到下面實現自動加載
        self::$fallbackDirsPsr4[] = rtrim(EXTEND_PATH, DS);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章