composer的autoloader源码追踪

首先理顺一下文件加载先后顺序


上面这几个文件都是在执行composer install 后生成的,那么问题来了,这些文件是怎么生成的?

追踪源码,可以发现生成逻辑如下:

首先composer/installer.php文件中执行到run()函数中,下载完所有依赖包,生成composer.lock文件后,就开始执行这段代码


最后一句

$this->autoloadGenerator->dump()就是生成代码核心
也就是这个文件composer\src\Composer\Autoload\AutoloadGenerator.php

首先确定好两个目录变量

$vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
$vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);

$appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
$appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);

然后依次从先前下载的所有依赖包获取自动加载设置

// Collect information from all packages.
$packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
$autoloads = $this->parseAutoloads($packageMap, $mainPackage); 
parseAutoloads()函数代码如下
public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
{
    $mainPackageMap = array_shift($packageMap);
    $sortedPackageMap = $this->sortPackageMap($packageMap);
    $sortedPackageMap[] = $mainPackageMap;
    array_unshift($packageMap, $mainPackageMap);

    $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
    $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
    $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
    $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
    $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);

    krsort($psr0);
    krsort($psr4);

    return array(
        'psr-0' => $psr0,
        'psr-4' => $psr4,
        'classmap' => $classmap,
        'files' => $files,
        'exclude-from-classmap' => $exclude,
    );
}

这些配置都在各个依赖包的composer.json中;

然后先生成namespaceFile

// Process the 'psr-0' base directories.
foreach ($autoloads['psr-0'] as $namespace => $paths) {
    $exportedPaths = array();
    foreach ($paths as $path) {
        $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
    }
    $exportedPrefix = var_export($namespace, true);
    $namespacesFile .= "    $exportedPrefix => ";
    $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
}
$namespacesFile .= ");\n";

再生成psr4File

// Process the 'psr-4' base directories.
foreach ($autoloads['psr-4'] as $namespace => $paths) {
    $exportedPaths = array();
    foreach ($paths as $path) {
        $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
    }
    $exportedPrefix = var_export($namespace, true);
    $psr4File .= "    $exportedPrefix => ";
    $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
}
$psr4File .= ");\n";

再生成classmapFile

ksort($classMap);
foreach ($classMap as $class => $code) {
    $classmapFile .= '    '.var_export($class, true).' => '.$code;
}
$classmapFile .= ");\n";

最后导入到文件中

file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);

另外还生成这几个文件

file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
$this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
$this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
完毕!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值