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();