上节已经把命名空间和目录的映射都赋值给了Loader的相关属性了。此时在使用一个不存在的类时,就可以触发Loader的autoload方法进行自动加载了。
我们看一下上一节执行完成后,Loader类的属性值情况
```
class Loader {
...
$prefixLengthsPsr4 = [
"t" => [
"think\composer\" => 15,
"think\" => 6 ,
"traits\" => 7
],
"a" => [ "app\" => 4 ]
]
$prefixDirsPsr4 = [
"think\\composer\\" => " /Users/lihui/Documents/tp/tp5.1/vendor/composer/../topthink/think-installer/src ",
"app\\" => "/Users/lihui/Documents/tp/tp5.1/vendor/composer/../../application",
"think\\" => "/Users/lihui/Documents/tp/tp5.1/thinkphp/library/think",
"traits\\" => "/Users/lihui/Documents/tp/tp5.1/thinkphp/library/traits"
]
$fallbackDirsPsr4 = ["/Users/lihui/Documents/tp/tp5.1/extend"]
...
}
```
## autoload方法实现自动加载
在代码中使用一个不存在的类时,会触发autoload方法,首页会查找$classAlias属性,是否定义了类的别名。如果定义了类的别名和实际类的映射。则可通过类的别名直接使用该类。**主要是通过php内置函数class_alias函数实现**
```
if (isset(self::$classAlias[$class])) {
return class_alias(self::$classAlias[$class], $class);
}
```
若没有定义类的别名和实际类的映射,则需要走命名空间的映射来找到实际类,并加载。
```
// 查找 PSR-4
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
$first = $class[0];
if (isset(self::$prefixLengthsPsr4[$first])) {
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;
}
}
}
}
}
// 查找 PSR-4 fallback dirs
foreach (self::$fallbackDirsPsr4 as $dir) {
if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
```
最终找到文件在系统中的位置,然后调用include 加载文件。
```
__include_file($file);
return true;
```