Composer自动加载机制源码剖析
来源:互联网 发布:linux less 向上查找 编辑:程序博客网 时间:2024/05/16 12:37
1、autoload.php
要使用Composer的自动加载,首先需要引入该文件
<?php// autoload.php @generated by Composer// 引入autoload_real.phprequire_once __DIR__ . '/composer' . '/autoload_real.php';// 下面一大长串是在我们安装composer时由Composer自动生成的,我们需要关注的是它调用的autoload_real.php里的静态方法 getLoader()return ComposerAutoloaderInit85b4dbf6b714d62ec745fcf3dd1a5041::getLoader();
2、autoload_real.php
<?php// autoload_real.php @generated by Composerclass ComposerAutoloaderInit85b4dbf6b714d62ec745fcf3dd1a5041{ private static $loader; // 在实例化ClassLoader时调用该函数 public static function loadClassLoader($class) { // 该函数在getLoader方法里被注册为__autoload的实现,在实例化类时,如果类不存在,会自动调用该方法 // 如果实例化的函数是Composer\Autoload\ClassLoader 则引入该类 if ('Composer\Autoload\ClassLoader' === $class) { require __DIR__ . '/ClassLoader.php'; } } public static function getLoader() { if (null !== self::$loader) { return self::$loader; }// 注册 loadClassLoader函数作为 __autoload 的实现 spl_autoload_register(array('ComposerAutoloaderInit85b4dbf6b714d62ec745fcf3dd1a5041', 'loadClassLoader'), true, true); // 实例化该方法时会自动调用上述方法注册的函数, // loadClassLoader函数里引入 ClassLoader类 self::$loader = $loader = new \Composer\Autoload\ClassLoader(); spl_autoload_unregister(array('ComposerAutoloaderInit85b4dbf6b714d62ec745fcf3dd1a5041', 'loadClassLoader')); // PSR-0 的规则 $map = require __DIR__ . '/autoload_namespaces.php'; foreach ($map as $namespace => $path) { $loader->set($namespace, $path); } // PSR-4 的规则 $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); } // 注册给定的函数作为 __autoload 的实现,具体参考下文 // Class-Map部分 $loader->register(true); // Files方式 直接加载需要访问的文件 $includeFiles = require __DIR__ . '/autoload_files.php'; foreach ($includeFiles as $fileIdentifier => $file) { composerRequire85b4dbf6b714d62ec745fcf3dd1a5041($fileIdentifier, $file); } return $loader; }}function composerRequire85b4dbf6b714d62ec745fcf3dd1a5041($fileIdentifier, $file){ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { // 加载需要调用的文件 require $file; $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; }}
3、ClassLoader.php (部分核心代码)
① 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 */ // $prefix、$paths分别相当于autoload_namespaces.php里返回数组的key和value值 public function set($prefix, $paths) { if (!$prefix) { $this->fallbackDirsPsr0 = (array) $paths; } else { // $prefix[0]取得是首个字符 $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); // PSR-4 命名空间以 \ 结尾,如果不是,则不符合规则 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; } }
③ 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; } } /** * Registers this instance as an autoloader. * * @param bool $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { // $prepend为true时,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。 (具体请参考php文档) spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * 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; } }
什么时候才会去调用上述注册的loadClass函数呢?举例来说
<?php require './vendor/autoload.php';// 当我们实例化TestController的时候,就会自动调用spl_autoload_register注册的函数loadClass,在loadClass中又会去调用findFile方法去查找类文件所在的位置,然后require引入$test = new TestController;echo $test->show();
至此Composer自动加载流程已讲述完毕。具体的代码还需各位自己去研究。不得不惊叹,有了Composer真是太方便了!
0 0
- Composer自动加载机制源码剖析
- Composer自动加载机制
- 详解composer的自动加载机制
- Composer中的自动加载
- Composer中的自动加载
- Composer中的自动加载
- Composer自动加载功能
- Composer中的自动加载
- composer 自动加载原理
- Composer自动加载实现
- 云客Drupal8源码分析之自动加载器与Composer
- composer概述及自动加载
- composer dumpautoload自动加载命令
- laravel composer自动加载函数
- composer中自动加载文件
- composer应用(一)自动加载
- 使用composer自动加载php命名空间
- yii2框架-composer的自动加载(二)
- Multiple markers at this line @Override的解决方法
- JNI_Android项目中调用.so动态库实现详解(初探)
- react-native Navigator 填坑
- linux系统启动过程详解-开机加电后发生了什么 --linux内核剖析(零)
- Xcode因为证书问题经常报的那些错
- Composer自动加载机制源码剖析
- 腾讯实习生面试一面笔试题总结
- HTML5新控件 - 数值输入框
- 判断字符串长度,中英文混合
- 笔试题:操作系统 (1)
- idea创建maven项目(web)
- 给 Android 开发者的 RxJava 详解
- UNIX网络编程 poll函数
- Java之——运行Python脚本的几种方式