Composer如何实现自动加载原理

小编给大家分享一下Composer如何实现自动加载原理,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!

1. 入口文件

(/public/index.php)中引入了 autoload.php

Composer如何实现自动加载原理

require__DIR__.'/../vendor/autoload.php';

2. autoload.php

require_once__DIR__.'/composer/autoload_real.php';
returnComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader();

3. autoload_real.php

<?php
//autoload_real.php@generatedbyComposer
classComposerAutoloaderInit1215780529014c2b50a6fca7ce889273{
privatestatic$loader;
publicstaticfunctionloadClassLoader($class){
if('Composer\Autoload\ClassLoader'===$class){
require__DIR__.'/ClassLoader.php';
}
}
publicstaticfunctiongetLoader(){
if(null!==self::$loader){
returnself::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273','loadClassLoader'),true,true);
self::$loader=$loader=new\Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273','loadClassLoader'));
$useStaticLoader=PHP_VERSION_ID>=50600&&!defined('HHVM_VERSION')&&(!function_exists('zend_loader_file_encoded')||!zend_loader_file_encoded());
if($useStaticLoader){
require_once__DIR__.'/autoload_static.php';

call_user_func(\Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::getInitializer($loader));
}else{
$map=require__DIR__.'/autoload_namespaces.php';
foreach($mapas$namespace=>$path){
$loader->set($namespace,$path);
}
$map=require__DIR__.'/autoload_psr4.php';
foreach($mapas$namespace=>$path){
$loader->setPsr4($namespace,$path);
}
$classMap=require__DIR__.'/autoload_classmap.php';
if($classMap){
$loader->addClassMap($classMap);
}
}
$loader->register(true);
if($useStaticLoader){
$includeFiles=Composer\Autoload\ComposerStaticInit1215780529014c2b50a6fca7ce889273::$files;
}else{
$includeFiles=require__DIR__.'/autoload_files.php';
}
foreach($includeFilesas$fileIdentifier=>$file){
composerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier,$file);
}

return$loader;
}
}
functioncomposerRequire1215780529014c2b50a6fca7ce889273($fileIdentifier,$file){
if(empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])){
require$file;

$GLOBALS['__composer_autoload_files'][$fileIdentifier]=true;
}
}

可以看出这一段是 composer 自动加载的重点,首先在 autoload.php 中调用

ComposerAutoloaderInit1215780529014c2b50a6fca7ce889273::getLoader () 方法,getLoader () 首先判断当前loader是不是null,如果不为null就直接返回,否则就初始化一个ClassLoader类给赋值给 loader 是不是 null,如果不为 null 就直接返回,否则就初始化一个 ClassLoader 类给赋值给 loader,接着将 autoload_namespaces.php、autoload_psr4.php、autoload_classmap.php 文件中的内容加入到 $loader 中对应的数组中,然后给注册 loadClass 函数,将 autoload_files.php 中的所有路径所示的文件都包含进来,当在 new 一个类的时候如果没有找到相关的类就会触发这个 loadClass 函数,在 loadClass () 又调用了 findFile () 去查找相应的文件,找到相应文件后就会返回该文件,然后 loadClass 调用 includeFile () 方法将该文件 include 进去,否则 findFile 返回 false,这样就完成了自动加载

4. findFile ()

publicfunctionfindFile($class){
//classmaplookup
if(isset($this->classMap[$class])){
return$this->classMap[$class];
}
if($this->classMapAuthoritative||isset($this->missingClasses[$class])){
returnfalse;
}
if(null!==$this->apcuPrefix){
$file=apcu_fetch($this->apcuPrefix.$class,$hit);
if($hit){
return$file;
}
}
$file=$this->findFileWithExtension($class,'.php');
//SearchforHackfilesifwearerunningonHHVM
if(false===$file&&defined('HHVM_VERSION')){
$file=$this->findFileWithExtension($class,'.hh');
}
if(null!==$this->apcuPrefix){
apcu_add($this->apcuPrefix.$class,$file);
}
if(false===$file){
//Rememberthatthisclassdoesnotexist.
$this->missingClasses[$class]=true;
}
return$file;
}

privatefunctionfindFileWithExtension($class,$ext){
//PSR-4lookup
$logicalPathPsr4=strtr($class,'\\',DIRECTORY_SEPARATOR).$ext;

$first=$class[0];
if(isset($this->prefixLengthsPsr4[$first])){
$subPath=$class;
while(false!==$lastPos=strrpos($subPath,'\\')){
$subPath=substr($subPath,0,$lastPos);
$search=$subPath.'\\';
if(isset($this->prefixDirsPsr4[$search])){
$pathEnd=DIRECTORY_SEPARATOR.substr($logicalPathPsr4,$lastPos+1);
foreach($this->prefixDirsPsr4[$search]as$dir){
if(file_exists($file=$dir.$pathEnd)){
return$file;
}
}
}
}
}
//PSR-4fallbackdirs
foreach($this->fallbackDirsPsr4as$dir){
if(file_exists($file=$dir.DIRECTORY_SEPARATOR.$logicalPathPsr4)){
return$file;
}
}

//PSR-0lookup
if(false!==$pos=strrpos($class,'\\')){
//namespacedclassname
$logicalPathPsr0=substr($logicalPathPsr4,0,$pos+1)
.strtr(substr($logicalPathPsr4,$pos+1),'_',DIRECTORY_SEPARATOR);
}else{
//PEAR-likeclassname
$logicalPathPsr0=strtr($class,'_',DIRECTORY_SEPARATOR).$ext;
}

if(isset($this->prefixesPsr0[$first])){
foreach($this->prefixesPsr0[$first]as$prefix=>$dirs){
if(0===strpos($class,$prefix)){
foreach($dirsas$dir){
if(file_exists($file=$dir.DIRECTORY_SEPARATOR.$logicalPathPsr0)){
return$file;
}
}
}
}
}

//PSR-0fallbackdirs
foreach($this->fallbackDirsPsr0as$dir){
if(file_exists($file=$dir.DIRECTORY_SEPARATOR.$logicalPathPsr0)){
return$file;
}
}
//PSR-0includepaths.
if($this->useIncludePath&&$file=stream_resolve_include_path($logicalPathPsr0)){
return$file;
}
returnfalse;
}

findFile () 函数先在 classMap 中查找,如果找不到的话就会尝试在 apcu 缓存中查找,如果还是找不到的话就会调用 findFileWithExtension () 函数查找,如果找到了就会将该文件加到apcu缓存,如果找不到的话就会在 missingClasses 数组中设一个标记表示识这个类找不到findFileWithExtension()方法根据之前通过loader->set(loader−>set(namespace, path)和path)和loader->setPsr4(namespace,namespace,path)方法设置的信息找出类文件的路径信息

5. spl_autoload_register和spl_autoload_unregister函数

1. spl_autoload_register 函数

1.spl_autoload_register — 注册给定的函数作为 __autoload 的实现,

bool spl_autoload_register([callable autoloadfunction[,boolautoloadfunction[,boolthrow = true [, bool $prepend = false ]]])

2.prepend

如果是 true,spl_autoload_register () 会添加函数到队列之首,而不是队列尾部。

3.如果在你的程序中已经实现了 autoload () 函数,它必须显式注册到 autoload () 队列中。因为 spl_autoload_register () 函数会将 Zend Engine 中的__autoload () 函数取代为 spl_autoload () 或 spl_autoload_call ()

例:

function __autoload($name) { require 'class/'.$name.'.php'; echo '1'; } function autoload_test($name) { echo '2'; } spl_autoload_register('autoload_test'); spl_autoload_register('__autoload'); $ca=new Ca();

2. spl_autoload_unregister 函数

spl_autoload_unregister — 注销已注册的 autoload () 函数,如果该函数队列处于激活状态,并且在给定函数注销后该队列变为空,则该函数队列将会变为无效。如果该函数注销后使得自动装载函数队列无效,即使存在有 autoload 函数它也不会自动激活。

bool spl_autoload_unregister ( mixed $autoload_function )

看完了这篇文章,相信你对“Composer如何实现自动加载原理”有了一定的了解,如果想了解更多相关知识,欢迎关注恰卡编程网行业资讯频道,感谢各位的阅读!

发布于 2021-05-30 14:09:58
收藏
分享
海报
0 条评论
182
上一篇:SpringBoot + WebSocket如何实现答题对战匹配机制案例详解 下一篇:js中MomentJS构造字符串的方法
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码