Composer有4种自动加载方式:file
,classmap
,psr-0
,psr-4
。本篇主要讲解file。
首先在网站目录下,新建一个文件名为Controller.php的文件,代码如下:
class Controller
{
public function test()
{
echo "Controller::test\n";
}
}
原始加载方式
PHP最原始的加载方式,是在PHP文件头部require需要加载的文件。
例如在网站目录下,新建一个index.php,内容如下:
require 'Controller.php'
$c = new Controller();
$c->test();
运行文件将显示结果:Controller::test
使用composer自动加载
composer安装
略。参考:http://www.884358.com/composer/
生成composer.json文件
在网站目录输入如下命令:
composer init
一直回车即可自动生成一个composer.json文件
生成autoload代码
输入如下命令:
composer install
稍等片刻,网站目录就会多出一个vendor文件夹
修改index.php代码
将index.php代码修改为:
<?php
require 'vendor/autoload.php';
$c = new Controller();
$c->test();
运行index.php,得到的结果如下:
提示Controller类找不到,原因就是没有将Controller类加载进来。
FILE自动加载方式
修改composer.json文件,在里面新增一个autoload
的key值,在autoload
里面有一个名为files
的key,值为需要加载的文件路径。
{
"name": "dedemao/composer_test",
"authors": [
{
"name": "884358",
"email": "884358@qq.com"
}
],
"require": {},
"autoload":{
"files":["Controller.php"]
}
}
然后运行命令composer dump-autoload
来重新生成autoload配置文件。
然后运行index.php,结果如下:
可以看到结果正常了。
自动加载执行流程分析
index.php第一行首先是引入了vendor/autoload.php
文件,打开vendor/autoload.php
文件,可以看到程序将要执行composer/autoload_real.php
文件中的getLoader函数。getLoader函数代码如下:
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit4d5ff8a105543c170ef7606290bd9ca9', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit4d5ff8a105543c170ef7606290bd9ca9', '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\ComposerStaticInit4d5ff8a105543c170ef7606290bd9ca9::getInitializer($loader));
} else {
}
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit4d5ff8a105543c170ef7606290bd9ca9::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire4d5ff8a105543c170ef7606290bd9ca9($fileIdentifier, $file);
}
return $loader;
}
函数首先是判断了自身类的$loader属性是否有内容,如果有则直接返回,否则继续向下执行。
然后通过自动加载函数,将ClassLoader.php
文件加载了进来,并new了一个ClassLoader对象放到自身的$loader属性。
紧接着,判断php版本如果大于5.6且不支持HHVM虚拟机则使用autoload_static.php
进行静态初始化。(PS:静态初始化只支持PHP5.6以上版本并且不支持HHVM虚拟机)
查看autoload_static.php
,可以看到有一个静态的成员变量files
,该变量是一个二维数组,存放的是需要自动加载的类文件。数组由一个hash随机数的键和需要加载的类文件的路径值组合,同时还有一个静态方法:getInitializer
,可以看到该方法返回的是一个匿名函数。
回到autoload_real.php
,下一步是$loader->register(true);
注册自动加载函数,打开ClassLoader.php
文件,其中register的代码为:
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
可以看出,一旦类文件找不到时,就会将找不到的类名传递到ClassLoader.php
里的loadClass
方法中。
再回到autoload_real.php
,下一步是将autoload_static.php
中的静态的成员变量files
赋值到变量$includeFiles
,接着通过循环遍历$includeFiles
,依次将$includeFiles
数组中的存放的文件路径require进来。
整个加载流程结束。
结论
通过分析autoload的执行流程可以看出,如果在composer.json文件中定义了files方式的自动加载,files里面指定的文件路径会在一开始就require进来,而不是按需加载的。
扩展资料
PHP自定加载原理:http://www.884358.com/php-autoload/