Composer如何实现自动加载原理
小编给大家分享一下Composer如何实现自动加载原理,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!
1. 入口文件
(/public/index.php)中引入了 autoload.php
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如何实现自动加载原理”有了一定的了解,如果想了解更多相关知识,欢迎关注恰卡编程网行业资讯频道,感谢各位的阅读!