:-: 自动加载
~~~
/**
* 类名映射信息
* @var array
*/
protected static $map = [];
/**
* 类库别名
* @var array
*/
protected static $classAlias = [];
/**
* PSR-4
* @var array
*/
private static $prefixLengthsPsr4 = [];
private static $prefixDirsPsr4 = [];
private static $fallbackDirsPsr4 = [];
/**
* PSR-0
* @var array
*/
private static $prefixesPsr0 = [];
private static $fallbackDirsPsr0 = [];
/**
* 自动加载的文件列表
* @var array
*/
private static $autoloadFiles = [];
/**
* Composer安装路径
* @var string
*/
private static $composerPath;
~~~
#### 自动加载
~~~
// 注册自动加载机制
public static function register($autoload = '')
{
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);
// 注册命名空间定义
self::addNamespace([
'think' => __DIR__ . '/',
'traits' => __DIR__ . '/../traits/',
]);
$path = dirname($_SERVER['SCRIPT_FILENAME']);
if (is_file('./think')) {
$rootPath = realpath($path) . '/';
} else {
$rootPath = realpath($path . '/../') . '/';
}
// 加载类库映射文件
if (is_file($rootPath . 'runtime/classmap.php')) {
self::addClassMap(__include_file($rootPath . 'runtime/classmap.php'));
}
self::$composerPath = $rootPath . 'vendor/composer/';
// Composer自动加载支持
if (is_dir(self::$composerPath)) {
self::registerComposerLoader(self::$composerPath);
}
// 自动加载extend目录
self::addAutoLoadDir($rootPath . 'extend');
}
// 自动加载
public static function autoload($class)
{
if (isset(self::$classAlias[$class])) {
return class_alias(self::$classAlias[$class], $class);
}
if ($file = self::findFile($class)) {
// Win环境严格区分大小写
if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
return false;
}
__include_file($file);
return true;
}
}
~~~
[spl_autoload_register](http://php.net/manual/zh/function.spl-autoload-register.php) — 注册给定的函数作为 __autoload 的实现 ;将函数注册到SPL __autoload函数队列中。如果该队列中的函数尚未激活,则激活它们。
[`pathinfo`](http://www.php.net/pathinfo) — 返回文件路径的信息
`spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);` 自动加载运行了 `autoload` 函数
[`$_SERVER['SCRIPT_FILENAME']`](http://php.net/manual/zh/reserved.variables.server.php)当前执行脚本的绝对路径。
[realpath](http://php.net/manual/zh/function.realpath.php) — 返回规范化的绝对路径名;realpath() 扩展所有的符号连接并且处理输入的 path 中的 '/./', '/../' 以及多余的 '/' 并返回规范化后的绝对路径名。返回的路径中没有符号连接,'/./' 或 '/../' 成分。
`self::addAutoLoadDir($rootPath . 'extend');` 设置 extend 文件目录为附加配置目录
~~~
// 添加Ps0空间
private static function addPsr0($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
self::$fallbackDirsPsr0 = array_merge(
(array) $paths,
self::$fallbackDirsPsr0
);
} else {
self::$fallbackDirsPsr0 = array_merge(
self::$fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset(self::$prefixesPsr0[$first][$prefix])) {
self::$prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
self::$prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
self::$prefixesPsr0[$first][$prefix]
);
} else {
self::$prefixesPsr0[$first][$prefix] = array_merge(
self::$prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
// 添加Psr4空间
private static function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
self::$fallbackDirsPsr4 = array_merge(
(array) $paths,
self::$fallbackDirsPsr4
);
} else {
self::$fallbackDirsPsr4 = array_merge(
self::$fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset(self::$prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
self::$prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
self::$prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
self::$prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
self::$prefixDirsPsr4[$prefix] = array_merge(
self::$prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
~~~
#### 文件加载
~~~
// 自动加载
public static function autoload($class)
{
}
include 加载文件
~~~
[`class_alias`](http://php.net/manual/zh/function.class-alias.php) — 为一个类创建别名
`registerComposerLoader($composerPath)` 函数加载 `vendor/composer/` 下的Composer文件
`addAutoLoadDir` 函数加载 `extend` 下的配置文件
因为 使用了 注册系统自动加载 `spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);`
所以 在引用Loader 之后的操作都会自动运行 `autoload` 方法 进行 `PSR` 加载 `think` 目录下的文件
例如:
`A:b(); // 运行think 目录下 A.php 文件类的 b(); 方法`