compoesr 解析流程
composer
加载文件
autoload.php
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitc8e7e2ff9618f4a7666639dbd0c65a25::getLoader();
在 autoload.php
文件中通过 require_once
引入autoload_real.php
文件, 在调用 ComposerAutoloaderInitc8e7e2ff9618f4a7666639dbd0c65a25::getLoader();
获取加载器
autoload_real.php
getLoader
方法
- 判断是否加载器是否已经存在, 加载器存在就返回
if (null !== self::$loader) {
return self::$loader;
}
- 通过
spl_autoload_register
调用自身loadClassLoader
方法
spl_autoload_register(array('ComposerAutoloaderInitc8e7e2ff9618f4a7666639dbd0c65a25', 'loadClassLoader'), true, true);
loadClassLoader
方法中验证传递$class
变量是否等于Composer\Autoload\ClassLoader
, 相等的话使用require
引入ClassLoader
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
- 通过
loadClassLoader
方法中引入的ClassLoader
类来创建加载器
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
- 通过
spl_autoload_unregister
注销已经引入的类
spl_autoload_unregister(array('ComposerAutoloaderInitc8e7e2ff9618f4a7666639dbd0c65a25', 'loadClassLoader'));
- 判断当前
php
版本和运许环境
PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
- 使用
PHP_VERSION_ID
判断当前php
版本 - 使用
HHVM_VERSION
判断是否已经定义, 存在代表是当前运行环境是HHVM
- 判断
zend_loader_file_encoded
方法是否存在, 存在调用该方法在取反
- 根据
$useStaticLoader
状态判断
$useStaticLoader
为true
引入 autoload_static.php
文件, 调用 ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25
类中 getInitializer
静态方法获取闭包函数, 在使用 call_user_func
调用闭包方法
require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::getInitializer($loader));
在 getInitializer
方法中注册了, 命名空间($prefixLengthsPsr4
), 命名空间路径($prefixDirsPsr4
), $prefixesPsr0
, 类文件映射($classMap
)
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::$prefixesPsr0;
$loader->classMap = ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::$classMap;
}, null, ClassLoader::class);
}
$useStaticLoader
为false
手动引入文件和注册
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
- 调用加载器的
register
方法
$loader->register(true);
register
方法这个放在后面说, 放在这里会影响内容
- 引入自动加载文件
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitc8e7e2ff9618f4a7666639dbd0c65a25::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
判断 $useStaticLoader
的状态来选择文件加载方式
- 注册加载文件到
$GLOBALS
全局变量中
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequirec8e7e2ff9618f4a7666639dbd0c65a25($fileIdentifier, $file);
}
循环调用 composerRequirec8e7e2ff9618f4a7666639dbd0c65a25
方法
function composerRequirec8e7e2ff9618f4a7666639dbd0c65a25($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}
composerRequirec8e7e2ff9618f4a7666639dbd0c65a25
方法是否已经引入, 没有引入先入文件在赋值到 $GLOBALS
全局变量中
- 最后返回加载器
ClassLoader.php
register
方法
使用 spl_autoload_register
调用自己 loadClass
方法加载类
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
loadClass
方法
通过 findFile
加载 $class
文件路径, 通过 includeFile
方法加载文件
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
includeFile
方法
使用 include
引入文件
function includeFile($file)
{
include $file;
}
findFile
方法
- 使用
classMap
映射返回文件
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
classMapAuthoritative
和missingClasses
判断是否返回false
classMapAuthoritative
目前也清楚是干嘛的missingClasses
判断这个是否为缺失状态
apcuPrefix
不为null
, 使用apcu_fetch
获取文件
if (null !== $this->apcuPrefix) {
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
if ($hit) {
return $file;
}
}
- 使用
findFileWithExtension
查询文件
- 查询
.php
文件 或者.hh
文件
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if (false === $file && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
- 如果
apcuPrefix
不为null
, 使用apcu_add
把文件添加到缓存中
if (null !== $this->apcuPrefix) {
apcu_add($this->apcuPrefix.$class, $file);
}
- 如果文件不存在, 标记为缺失状态
if (false === $file) {
// Remember that this class does not exist.
$this->missingClasses[$class] = true;
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: