目录
- composer
- autoload_classmap.php
- autoload_files.php:助手文件
- autoload_real.php:自动加载逻辑
- autoload_static.php:
- autoload_psr4.php:PSR4配置文件
- autoload_namespace.php:PSR0配置文件
- ClassLoader.php:类加载器实现一个PSR-0、PSR-4和classmap类加载器。
- autoload.php:入口文件,加载 autoload_real.php 文件 调用加载器 getLoader()
生命周期
- autoload.php:入口文件,加载 autoload_real.php 文件 调用加载器 getLoader()
- autoload_real.php getLoader() 静态方法,注册loadClassLoader用来加载初始化ClassLoader类
- 判断是否支持静态初始化(静态初始化只支持 PHP5.6 以上版本并且不支持 HHVM 虚拟机)
这一过程主要将缓存的文件加载进程序,赋值给ClassLoader的属性- 支持静态初始化 加载autoload_static.php 文件
- 不支持
- 加载 autoload_namespaces.php
- 加载 autoload_psr4.php’
- 加载 autoload_classmap.php
- 将 ClassLoader::loadClass注册为自动加载函数
- 加载 autoload_files.php 助手文件
类的加载
类的加载调用ClassLoader::loadClass文件,顺序如下
调用 findFile 查找具体文件
- 在 classMap 数组中查找类 找到返回
- 如果使用 composer —class-authorizative 或者 该类被标记为missing 返回false
- 如果开启了 apcu扩展,在apcu扩展中查找
在系统文件中查找(通过类名和后缀) ```php /**
- 在文件系统中查找类
- @param string $class 要查找的类
- @param string $ext 后缀
@return bool|false|string / private function findFileWithExtension($class, $ext) { /*
- PSR-4 lookup
在符合 PSR-4 规范的集合中查找 */ // $class = App\Http\Controllers\Home\HomeController // $ext = .php // $logicalPathPsr4 = App/Http/Controllers/Home/HomeController.php $logicalPathPsr4 = strtr($class, ‘\‘, DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];// A // 查找前缀数组 // $first = A if (isset($this->prefixLengthsPsr4[$first])) { // $subPath = App\Http\Controllers\Home\HomeController $subPath = $class; // 循环逐级向上查找 // 第一次循环 $lastPos = 25 $subPath = App\Http\Controllers\Home $search = App\Http\Controllers\Home\ // 第二次循环 $lastPos = 20 $subPath = App\Http\Controllers $search = App\Http\Controllers\ // 第三次循环 $lastPos = 8 $subPath = App\Http $search = App\Http\ // 第四次循环 $lastPos = 3 $subPath = App $search = App\ // 查找到App\返回文件地址 $pathEnd = /Http/Controllers/Home/HomeController.php // $logicalPathPsr4 = App/Http/Controllers/Home/HomeController.php
while (false !== $lastPos = strrpos($subPath, ‘\‘)) {
$subPath = substr($subPath, 0, $lastPos);$search = $subPath . '\\';// Illuminate\Foundation\if (isset($this->prefixDirsPsr4[$search])) { // 在Psr-4 前缀目录 对应数组中查找$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);// 在系统目录中查找文件,查找到返回foreach ($this->prefixDirsPsr4[$search] as $dir) {if (file_exists($file = $dir . $pathEnd)) {return $file;}}}
} }
// PSR-4 fallback dirs // 在fallbackDirsPsr4中查找文件 foreach ($this->fallbackDirsPsr4 as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
} }
/*** 在符合 PSR-0 规范的集合中查找* PSR-0 lookup**/// 如果包含命名空间if (false !== $pos = strrpos($class, '\\')) {// namespaced class name// 获取符合psr0规范的类名,包含命名空间// Dir1\Dir2\Dir3_ClassName1 ---> Dir1\Dir2/ClassName1$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1). strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);} else {// PEAR-like class name// PEAR的风格类// Dir1_Dir2_ClassName1 --->Dir1/Dir2/ClassName1$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;}if (isset($this->prefixesPsr0[$first])) {foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {if (0 === strpos($class, $prefix)) {foreach ($dirs as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {return $file;}}}}}// PSR-0 fallback dirsforeach ($this->fallbackDirsPsr0 as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {return $file;}}// PSR-0 include paths.if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {return $file;}return false;}
}
- 如果开启了HHVM 在hack文件中搜索- 开启 apcu 扩展,缓存查找目标信息- 没有找到 标记missing- 调用外部函数 includeFile 加载找到的文件<a name="5b804b05"></a>### 源码<a name="composer_real.php"></a>#### composer_real.php```php<?php// autoload_real.php @generated by Composerclass ComposerAutoloaderInite1402bdd050981d44622d2e1c72145b4{private static $loader;/*** 加载 ClassLoader.php* @param string $class 类名*/public static function loadClassLoader($class){if ('Composer\Autoload\ClassLoader' === $class) {// 如若是 Composer\Autoload\ClassLoader 类,包含当前目录下的ClassLoaderrequire __DIR__ . '/ClassLoader.php';}}// 注册加载器public static function getLoader(){if (null !== self::$loader) {return self::$loader;}// 注册self::loadClassLoader为自动加载函数,用来加载 ClassLoaderspl_autoload_register(array('ComposerAutoloaderInite1402bdd050981d44622d2e1c72145b4', 'loadClassLoader'), true, true);// 实例话ClassLoaderself::$loader = $loader = new \Composer\Autoload\ClassLoader();// 注销 self::loadClassLoader 为自动加载函数spl_autoload_unregister(array('ComposerAutoloaderInite1402bdd050981d44622d2e1c72145b4', 'loadClassLoader'));/*** 初始化 自动加载核心对象* 声明静态加载器:静态初始化只支持 PHP5.6 以上版本并且不支持 HHVM 虚拟机(Facebook 的一个为php提高性能的一个开源项目)* PHP_VERSION_ID:70322* defined('HHVM_VERSION'):false* zend_loader_file_encoded:如果当前文件是Zend编码的文件,则返回true。*/$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());if ($useStaticLoader) {// 支持静态加载,加载 autoload_static 文件require_once __DIR__ . '/autoload_static.php';// 调用匿名函数 实现静态加载(实际对加载器$loader属性赋值)call_user_func(\Composer\Autoload\ComposerStaticInite1402bdd050981d44622d2e1c72145b4::getInitializer($loader));} else {// 不支持静态加载,加载 autoload_namespaces 文件,使用命名空间$map = require __DIR__ . '/autoload_namespaces.php';// 遍历文件 设置 prefixesPsr0foreach ($map as $namespace => $path) {$loader->set($namespace, $path);}// 加载 autoload_psr4.php$map = require __DIR__ . '/autoload_psr4.php';// 遍历文件 设置 prefixLengthsPsr4 prefixDirsPsr4foreach ($map as $namespace => $path) {$loader->setPsr4($namespace, $path);}// 加载 autoload_classmap.php$classMap = require __DIR__ . '/autoload_classmap.php';// 配置存在 设置 classMapif ($classMap) {$loader->addClassMap($classMap);}}$loader->register(true);if ($useStaticLoader) {$includeFiles = Composer\Autoload\ComposerStaticInite1402bdd050981d44622d2e1c72145b4::$files;} else {$includeFiles = require __DIR__ . '/autoload_files.php';}foreach ($includeFiles as $fileIdentifier => $file) {composerRequiree1402bdd050981d44622d2e1c72145b4($fileIdentifier, $file);}return $loader;}}function composerRequiree1402bdd050981d44622d2e1c72145b4($fileIdentifier, $file){if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {require $file;$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;}}
ClassLoader.php
<?php/** This file is part of Composer.** (c) Nils Adermann <naderman@naderman.de>* Jordi Boggiano <j.boggiano@seld.be>** For the full copyright and license information, please view the LICENSE* file that was distributed with this source code.*/namespace Composer\Autoload;/*** ClassLoader implements a PSR-0, PSR-4 and classmap class loader.* 类加载器实现一个PSR-0、PSR-4和classmap类加载器。* $loader = new \Composer\Autoload\ClassLoader();** // register classes with namespaces* // 通过命名空间注册类 使用add()方法* $loader->add('Symfony\Component', __DIR__.'/component');* $loader->add('Symfony', __DIR__.'/framework');** // activate the autoloader* // 启动自动加载器 使用register()* $loader->register();** // to enable searching the include path (eg. for PEAR packages)* // 启用对include路径的搜索(例如PEAR包)* $loader->setUseIncludePath(true);** In this example,* if you try to use a class in the Symfony\Component namespace or one of its children* (Symfony\Component\Console for instance),* the autoloader will first look for the class under the component/ directory,* and it will then fallback to the framework/ directory* if not found before giving up.* 在本例中,如果您尝试使用Symfony\Component命名空间中的某个类或其子级之一* (例如Symfony\Component\Console),* 则autoloader将首先在Component/目录下查找该类,如果找不到该类,则会在放弃之前回退到framework/目录。** This class is loosely based on the Symfony UniversalClassLoader.* 这个类松散地(不精确的)基于Symfony UniversalClassLoader。** @author Fabien Potencier <fabien@symfony.com>* @author Jordi Boggiano <j.boggiano@seld.be>* @see http://www.php-fig.org/psr/psr-0/* @see http://www.php-fig.org/psr/psr-4/*/class ClassLoader{// PSR-4/*** PSR-4 前缀-长度 数组* @var array* ['p'] => array(* ['phpDocumentor\Reflection\'] => 25* ),* ['X'] => array(* ['XdgBaseDir\'] => 11* ),*/private $prefixLengthsPsr4 = array();// PSR-4 前缀-长度/*** PSR-4 前缀-目录* @var array* 'phpDocumentor\Reflection\'=>[* '/Users/sun/code/php/laravel/blog/vendor/composer/../phpdocumentor/reflection-common/src',* '/Users/sun/code/php/laravel/blog/vendor/composer/../phpdocumentor/reflection-docblock/src',* '/Users/sun/code/php/laravel/blog/vendor/composer/../phpdocumentor/type-resolver/src'* ]* 'XdgBaseDir\'=>[* '/Users/sun/code/php/laravel/blog/vendor/composer/../dnoegel/php-xdg-base-dir/src'* ]*/private $prefixDirsPsr4 = array(); // PSR-4 前缀目录private $fallbackDirsPsr4 = array(); // PSR-4 回退目录// PSR-0/*** @var array* 'M'=>[* 'Mockery'=>'/Users/sun/code/php/laravel/blog/vendor/composer/../mockery/mockery/library'* ]*/private $prefixesPsr0 = array();private $fallbackDirsPsr0 = array();private $useIncludePath = false; // 对include路径的搜索(例如PEAR包)/*** class 对应路径* @var array* 'phpDocumentor\Reflection\Utils'=>'/Users/sun/code/php/laravel/blog/vendor/composer/../phpdocumentor/reflection-docblock/src/Utils.php'*/private $classMap = array();private $classMapAuthoritative = false;private $missingClasses = array();private $apcuPrefix; // apcu 缓存前缀 null/*** 获取prefixesPsr0数组* @return array|mixed*/public function getPrefixes(){/*** 如果 PSR-0 数组不为空,合并 PSR-0 数组,并返回*/if (!empty($this->prefixesPsr0)) {// 调用回调函数,并把一个数组参数作为回调函数的参数// 作用:数组降低维度,二维降到一维数组return call_user_func_array('array_merge', $this->prefixesPsr0);}return array();}/*** 返回 prefixDirsPsr4* @return array*/public function getPrefixesPsr4(){return $this->prefixDirsPsr4;}/*** 获取 PSR-0 回退目录数组* @return array*/public function getFallbackDirs(){return $this->fallbackDirsPsr0;}/*** 获取 PSR-4 回退目录数组* @return array*/public function getFallbackDirsPsr4(){return $this->fallbackDirsPsr4;}/*** 获取 class Map* @return array*/public function getClassMap(){return $this->classMap;}/*** 添加 class Map* 如果存在,追加* @param array $classMap Class to filename map*/public function addClassMap(array $classMap){if ($this->classMap) {$this->classMap = array_merge($this->classMap, $classMap);} else {$this->classMap = $classMap;}}/*** 为一个给定的前缀注册一组PSR-0目录,可以将其附加到先前为此前缀设置的目录的前面或后面。* Registers a set of PSR-0 directories for a given prefix, either* appending or prepending to the ones previously set for this prefix.* 如果 $prefix 存在,$path 添加到prefixesPsr0中,否则添加到fallbackDirsPsr0中** @param string $prefix The prefix 前缀* @param array|string $paths The PSR-0 root directories PSR-0根目录* @param bool $prepend Whether to prepend the directories 是否在目录前*/public function add($prefix, $paths, $prepend = false){// 不存在前缀if (!$prefix) {// 是否添加到 Psr0回退目录 目录前if ($prepend) {// 添加到 Psr0回退目录 目录前$this->fallbackDirsPsr0 = array_merge((array) $paths,$this->fallbackDirsPsr0);} else {// 添加到 Psr0回退目录 目录后$this->fallbackDirsPsr0 = array_merge($this->fallbackDirsPsr0,(array) $paths);}return;}// 存在前缀$first = $prefix[0];// psr0 前缀数组中 不存在但前前缀if (!isset($this->prefixesPsr0[$first][$prefix])) {$this->prefixesPsr0[$first][$prefix] = (array) $paths;return;}// 按照 前置判断 合并前缀数组if ($prepend) {$this->prefixesPsr0[$first][$prefix] = array_merge((array) $paths,$this->prefixesPsr0[$first][$prefix]);} else {$this->prefixesPsr0[$first][$prefix] = array_merge($this->prefixesPsr0[$first][$prefix],(array) $paths);}}/*** 为给定的命名空间注册一组PSR-4目录,可以将其附加到先前为此命名空间设置的目录之前。* Registers a set of PSR-4 directories for a given namespace, either* appending or prepending to the ones previously set for this namespace.* 如果 $prefix 存在,* prefixDirsPsr4 存在 $path 更新到prefixesPsr4中,* prefixDirsPsr4 不存在 $path 添加到prefixesPsr4中,并设置prefixLengthsPsr4[$prefix[0]][$prefix] = $length;* 如果 $prefix 不存在,添加到fallbackDirsPsr4中** @param string $prefix The prefix/namespace, with trailing '\\' 前缀/命名空间,以\\结尾* @param array|string $paths The PSR-4 base directories* @param bool $prepend Whether to prepend the directories** @throws \InvalidArgumentException*/public function addPsr4($prefix, $paths, $prepend = false){if (!$prefix) {// Register directories for the root namespace.if ($prepend) {$this->fallbackDirsPsr4 = array_merge((array) $paths,$this->fallbackDirsPsr4);} else {$this->fallbackDirsPsr4 = array_merge($this->fallbackDirsPsr4,(array) $paths);}} elseif (!isset($this->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.");}$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;$this->prefixDirsPsr4[$prefix] = (array) $paths;} elseif ($prepend) {// Prepend directories for an already registered namespace.$this->prefixDirsPsr4[$prefix] = array_merge((array) $paths,$this->prefixDirsPsr4[$prefix]);} else {// Append directories for an already registered namespace.$this->prefixDirsPsr4[$prefix] = array_merge($this->prefixDirsPsr4[$prefix],(array) $paths);}}/*** 为给定前缀注册一组PSR-0目录,替换先前为此前缀设置的任何其他目录。* Registers a set of PSR-0 directories for a given prefix,* replacing any others previously set for this prefix.** @param string $prefix The prefix* @param array|string $paths The PSR-0 base directories*/public function set($prefix, $paths){if (!$prefix) {$this->fallbackDirsPsr0 = (array) $paths;} else {$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;}}/*** 为给定名称空间注册一组PSR-4目录,替换先前为此命名空间设置的任何其他项。* Registers a set of PSR-4 directories for a given namespace,* replacing any others previously set for this namespace.** @param string $prefix The prefix/namespace, with trailing '\\'* @param array|string $paths The PSR-4 base directories** @throws \InvalidArgumentException*/public function setPsr4($prefix, $paths){if (!$prefix) {$this->fallbackDirsPsr4 = (array) $paths;} else {$length = strlen($prefix);if ('\\' !== $prefix[$length - 1]) {// 非空的PSR-4前缀必须以命名空间分隔符结尾。throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");}$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;$this->prefixDirsPsr4[$prefix] = (array) $paths;}}/*** 启用对类文件的包含路径的搜索* Turns on searching the include path for class files.** @param bool $useIncludePath*/public function setUseIncludePath($useIncludePath){$this->useIncludePath = $useIncludePath;}/*** 可用于检查autoloader是否使用include路径检查类* Can be used to check if the autoloader uses the include path to check for classes.** @return bool*/public function getUseIncludePath(){return $this->useIncludePath;}/*** 关闭在前缀和回退目录中搜索尚未在类映射中注册的类* Turns off searching the prefix and fallback directories for classes* that have not been registered with the class map.** @param bool $classMapAuthoritative*/public function setClassMapAuthoritative($classMapAuthoritative){$this->classMapAuthoritative = $classMapAuthoritative;}/*** 如果在当前的类映射中找不到类,是否应该失败?* Should class lookup fail if not found in the current class map?** @return bool*/public function isClassMapAuthoritative(){return $this->classMapAuthoritative;}/*** APCu前缀,用于缓存已找到/未找到的类(如果已启用扩展)。* APCu prefix to use to cache found/not-found classes, if the extension is enabled.** @param string|null $apcuPrefix*/public function setApcuPrefix($apcuPrefix){/*** apcu_fetch:从缓存中提取变量* filter_var:函数通过指定的过滤器过滤一个变量。* ini_get():获取配置信息* FILTER_VAILIDATE:如果是 “1”, “true”, “on” 以及 “yes”,则返回 true,如果是 “0”, “false”, “off”, “no” 以及 “”,则返回 false。否则返回 NULL。** 判断是否开启APC User Cache,没有开启设置null,开启设置传递的值*/$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;}/*** 获取正在使用的APCu前缀,如果未启用APCu缓存,则为null。* The APCu prefix in use, or null if APCu caching is not enabled.** @return string|null*/public function getApcuPrefix(){return $this->apcuPrefix;}/*** 将此实例注册为自动加载程序* Registers this instance as an autoloader.** @param bool $prepend Whether to prepend the autoloader or not* 如果 $prepend 为true,则spl_autoload_register()将在自动加载堆栈上预加autoloader,而不是追加它。*/public function register($prepend = false){spl_autoload_register(array($this, 'loadClass'), true, $prepend);}/*** Unregisters this instance as an autoloader* 将此实例注销为自动加载程序*/public function unregister(){spl_autoload_unregister(array($this, 'loadClass'));}/*** 加载给定的类或接口。(spl_autoload_register注册的方法)* Loads the given class or interface.* 不存在不处理* @param string $class The name of the class 类名* @return bool|null True if loaded, null otherwise*/public function loadClass($class){if ($file = $this->findFile($class)) {includeFile($file);return true;}}/*** 查找定义类的文件的路径* Finds the path to the file where the class is defined.** @param string $class The name of the class** @return string|false The path if found, false otherwise*/public function findFile($class){// class map lookup// 将 PSR-4/PSR-0 的规则转化为了 classmap 的规则,在classMap中查找类if (isset($this->classMap[$class])) {return $this->classMap[$class];}// composer 配置 --class-authorizative。在classMap查找不到的时候,认为为非法类,不在检索文件系统// 已经被记录过一次的不存在的类,返回falseif ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {return false;}// 如果开启扩展 apcu ,在apcu中查找类// classmap 中找不到目标类时,将在文件系统中找到的结果存储到共享内存中, 当下次再查找时就可以从内存中直接返回,不用再去文件系统中再次查找。if (null !== $this->apcuPrefix) {$file = apcu_fetch($this->apcuPrefix.$class, $hit);if ($hit) {return $file;}}// 在文件系统中查找类$file = $this->findFileWithExtension($class, '.php');// Search for Hack files if we are running on HHVM// 如果我们在HHVM上运行,请搜索Hack文件if (false === $file && defined('HHVM_VERSION')) {$file = $this->findFileWithExtension($class, '.hh');}// classmap 中找不到目标类时,将在文件系统中找到的结果存储到共享内存中, 当下次再查找时就可以从内存中直接返回,不用再去文件系统中再次查找。if (null !== $this->apcuPrefix) {// 仅当变量尚未存储时,才在数据存储中缓存该变量apcu_add($this->apcuPrefix.$class, $file);}// 记住这个类不存在if (false === $file) {// Remember that this class does not exist.$this->missingClasses[$class] = true;}return $file;}/*** 在文件系统中查找类* @param string $class 要查找的类* @param string $ext 后缀* @return bool|false|string*/private function findFileWithExtension($class, $ext){/*** PSR-4 lookup* 在符合 PSR-4 规范的集合中查找*/// $class = App\Http\Controllers\Home\HomeController// $ext = .php// $logicalPathPsr4 = App/Http/Controllers/Home/HomeController.php$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;$first = $class[0];// A// 查找前缀数组// $first = Aif (isset($this->prefixLengthsPsr4[$first])) {// $subPath = App\Http\Controllers\Home\HomeController$subPath = $class;// 循环逐级向上查找// 第一次循环 $lastPos = 25 $subPath = App\Http\Controllers\Home $search = App\Http\Controllers\Home\// 第二次循环 $lastPos = 20 $subPath = App\Http\Controllers $search = App\Http\Controllers\// 第三次循环 $lastPos = 8 $subPath = App\Http $search = App\Http\// 第四次循环 $lastPos = 3 $subPath = App $search = App\// 查找到App\返回文件地址 $pathEnd = /Http/Controllers/Home/HomeController.php// $logicalPathPsr4 = App/Http/Controllers/Home/HomeController.phpwhile (false !== $lastPos = strrpos($subPath, '\\')) {$subPath = substr($subPath, 0, $lastPos);$search = $subPath . '\\';// Illuminate\Foundation\if (isset($this->prefixDirsPsr4[$search])) { // 在Psr-4 前缀目录 对应数组中查找$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);// 在系统目录中查找文件,查找到返回foreach ($this->prefixDirsPsr4[$search] as $dir) {if (file_exists($file = $dir . $pathEnd)) {return $file;}}}}}// PSR-4 fallback dirs// 在fallbackDirsPsr4中查找文件foreach ($this->fallbackDirsPsr4 as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {return $file;}}/*** 在符合 PSR-0 规范的集合中查找* PSR-0 lookup**/// 如果包含命名空间if (false !== $pos = strrpos($class, '\\')) {// namespaced class name// 获取符合psr0规范的类名,包含命名空间// Dir1\Dir2\Dir3_ClassName1 ---> Dir1\Dir2/ClassName1$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1). strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);} else {// PEAR-like class name// PEAR的风格类// Dir1_Dir2_ClassName1 --->Dir1/Dir2/ClassName1$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;}if (isset($this->prefixesPsr0[$first])) {foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {if (0 === strpos($class, $prefix)) {foreach ($dirs as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {return $file;}}}}}// PSR-0 fallback dirsforeach ($this->fallbackDirsPsr0 as $dir) {if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {return $file;}}// PSR-0 include paths.if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {return $file;}return false;}}/*** Scope isolated include.* 范围隔离包括(单独函数,非类方法)* Prevents access to $this/self from included files.* 阻止从包含的文件访问$this/self。*/function includeFile($file){include $file;}
