## base.php
框架base.php文件,首先載入Loader類,并執行Loader的靜態方法register,進行注冊自動加載
```
// 載入Loader類
require __DIR__ . '/library/think/Loader.php';
// 注冊自動加載
Loader::register();
```
可以自定義加載函數,并有register參數傳入。
```
public static function register($autoload = '') {
// 注冊系統自動加載
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true')
}
```
## Loader.php
由base.php中調用Loader的register靜態方法。該方法首先注冊一個自動加載函數。接著將框架的aplication,extend,composer的目錄和各自的命名空間相映射
#### 注冊自動加載
```
// 注冊系統自動加載
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
```
#### composer自動加載支持
獲取composer目錄
```
$rootPath = self::getRootPath(); // 項目的根目錄
self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;
```
載入composer自動加載文件,并將composer下載的安裝包關系映射賦值給Loader屬性。
$prefixLengthsPsr4,$prefixDirsPsr4兩個屬性描述了命名空間和實際目錄位置的映射。**當通過composer進行下載安裝包時,會自動更新composer的autoload_static.php的屬性**
```
// Composer自動加載支持
if (is_dir(self::$composerPath)) {
if (is_file(self::$composerPath . 'autoload_static.php')) {
require self::$composerPath . 'autoload_static.php';
// get_declared_classes函數獲取當前所有載入的類
$declaredClass = get_declared_classes();
$composerClass = array_pop($declaredClass);
foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
// 將composer的autoload_static.php類的prefixLengthsPsr4,prefixDirsPsr4屬性賦值給Loader的prefixLengthsPsr4, prefixDirsPsr4屬性
if (property_exists($composerClass, $attr)) {
self::${$attr} = $composerClass::${$attr};
}
}
} else {
self::registerComposerLoader(self::$composerPath);
}
}
```
由于composer的autoload_static.php中只定義了`think\composer` `app`和其他通過composer安裝的安裝包命名空間對于的目錄的映射。所以還需要把框架核心的`think``traits`命名空間的映射添加到Loader的$prefixLengthsPsr4,$prefixLengthsPsr4的屬性上
```
// 注冊命名空間定義
self::addNamespace([
'think' => __DIR__,
'traits' => dirname(__DIR__) . DIRECTORY_SEPARATOR . 'traits',
]);
```
將類庫的映射文件中的數據,載入到Loader屬性$classMap。類庫映射文件是需要手動生成的,里面是所有類名映射到類的絕對地址。
```
// 加載類庫映射文件
if (is_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php')) {
self::addClassMap(__include_file($rootPath . 'runtime' . DIRECTORY_SEPARATOR . 'classmap.php'));
}
```
extend擴展目錄的位置賦值給Loader類的$fallbackDirsPsr4。若自定義目錄也想要自動加載。可以參考extend的方式。
```
// 自動加載extend目錄
self::addAutoLoadDir($rootPath . 'extend')
```
最后在base.php文件中注冊了類的別名。在使用一個不存在的類時,優先判斷是否包含類的別名,在根據類的別名所對應的類來加載。
```
base.php
...
// 注冊類庫別名
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,
]);
```
到此,相關命名空間和目錄的映射都準備好了。