## 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,
]);
```
到此,相关命名空间和目录的映射都准备好了。