首先我們拿到框,肯定要先找到框架的入口文件,Thinkphp5.1的入口文件 `tp5_analyze\public\index.php`
```
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// [ 應用入口文件 ]
namespace think;
// 加載基礎文件
require __DIR__ . '/../thinkphp/base.php';
// 支持事先使用靜態方法設置Request對象和Config對象
// 執行應用并響應
Container::get('app')->run()->send();
```
我們可以看到在入口文件中,他會去加載基礎文件 `thinkphp/base.php` ,基礎文件所在目錄 `tp5_analyze\thinkphp\base.php`
```
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
// 載入Loader類
require __DIR__ . '/library/think/Loader.php';
// 注冊自動加載
Loader::register();
// 注冊錯誤和異常處理機制
Error::register();
// 實現日志接口
if (interface_exists('Psr\Log\LoggerInterface')) {
interface LoggerInterface extends \Psr\Log\LoggerInterface
{}
} else {
interface LoggerInterface
{}
}
// 注冊類庫別名
Loader::addClassAlias([
'App' => facade\App::class,
'Build' => facade\Build::class,
'Cache' => facade\Cache::class,
'Config' => facade\Config::class,
'Cookie' => facade\Cookie::class,
'Db' => Db::class,
'Debug' => facade\Debug::class,
'Env' => facade\Env::class,
'Facade' => Facade::class,
'Hook' => facade\Hook::class,
'Lang' => facade\Lang::class,
'Log' => facade\Log::class,
'Request' => facade\Request::class,
'Response' => facade\Response::class,
'Route' => facade\Route::class,
'Session' => facade\Session::class,
'Url' => facade\Url::class,
'Validate' => facade\Validate::class,
'View' => facade\View::class,
]);
```
在`base.php`中會去加載`Loader.php`這個文件或者說是類,這個類可以這么說,就是Thinkphp5自動加載的靈魂。可以看到加載的類 `Loader.php`,類所在目錄`thinkphp\library\think\Loader.php`,這個類庫就是Thinkphp5封裝的底層基礎類庫,這個類庫就是需要我們進行深度分析的類庫。
我們可以看到,在`base.php`中加載完`Loader.php`之后,會調用`Loader::register();`方法,我們追蹤進去可以看到這個方法
~~~
// 注冊自動加載機制
public static function register($autoload = '')
{
// 注冊系統自動加載
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
$rootPath = self::getRootPath();
self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;
// Composer自動加載支持
if (is_dir(self::$composerPath)) {
if (is_file(self::$composerPath . 'autoload_static.php')) {
require self::$composerPath . 'autoload_static.php';
$declaredClass = get_declared_classes();
$composerClass = array_pop($declaredClass);
foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
if (property_exists($composerClass, $attr)) {
self::${$attr} = $composerClass::${$attr};
}
}
} else {
self::registerComposerLoader(self::$composerPath);
}
}
// 注冊命名空間定義
self::addNamespace([
'think' => __DIR__,
'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits',
]);
// 加載類庫映射文件
if (is_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')) {
self::addClassMap(__include_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php'));
}
// 自動加載extend目錄
self::addAutoLoadDir($rootPath . 'extend');
}
~~~
這個方法其實就是注冊自動加載的機制。他把Thinkphp的加載與Composer的加載封裝到了一個文件,我們可以看到自動加載機制的方法里面,引入了Composer包里面的`autoload_static.php`,并針對Composer的這種方式做自動加載,這里先不啰嗦,我們會在后續的章節中詳細了解這個方法。
其他的框架在使用的時候,他們的邏輯是是一樣的,都會在框架的第一步實現自動加載。