PHP 的自动加载(持续学习更新中)
什么是自动加载
PHP 只能执行当前文件中的代码,但现代的工程化项目,都是由很多人的一起协作组成,不可能将所有代码写到一个文件中。那么,将其他人的代码包含到当前文件中,就是加载。区别于使用 require_once()
、require
等方法的手动加载,不进行显式加载的方式就是自动加载。PHP 中访问不存在的类时会调用 __autoload()
。
require 和 require_once 是怎么工作的
结论:require
和 require_once
就是把对应文件的代码放置到调用这 2 个方法的位置。
验证:
目录结构
- AnotherIndexClass.php
- index.php
- IndexClass.php
AnotherIndexClass.php
<?php
require_once 'IndexClass.php';
$indexClass->sayHello();
index.php
<?php
require_once 'IndexClass.php';
echo __FILE__ . ' : ' . __LINE__ . PHP_EOL;
$indexClass = new IndexClass();
require_once 'AnotherIndexClass.php';
IndexClass.php
<?php
require_once 'index.php';
class IndexClass
{
public function __construct()
{
echo self::class . ' - ' . __FUNCTION__ . PHP_EOL;
}
public function sayHello()
{
echo self::class . ' - ' . __FUNCTION__ . PHP_EOL;
}
}
echo __FILE__ . ' : ' . __LINE__ . PHP_EOL;
执行:php index.php
可以看到,因为是在 index.php
中引入的 IndexClass.php
,所以会先跑 IndexClass.php
中的代码,同时 AnotherIndexClass.php
中可以访问 index.php
中的变量($indexClass
),就好像将所有代码都糅合到了一个文件中,然后按顺序在执行。
执行:php IndexClass.php
可以看到,执行 php IndexClass.php
会和之前 php index.php
得到不一样的输出。也同样可以理解为将所有代码糅合到一个文件中,只不过之前是糅合到 index.php
中,而现在是糅合到 IndexClass.php
中。
require 和 require_once 的区别
require_once
会判断之前有没有引入过,就是因为加入了这个判断,require_once
的效率会要比 require
低很多。但同时,如果使用 require
,就很容易造成相互引用而陷入死循环。比如将上面 3 个文件中的 require_once
都替换为 reuqire
,我们会得到以下的输出。
即,什么都不会执行,陷入了引用地狱。
访问不存在的类时会怎么样
校验代码
<?php
function __autoload($className) {
echo ("from autoload:" . $className . PHP_EOL);
}
spl_autoload_register(function ($className) {
echo ("from spl - 1:" . $className . PHP_EOL);
});
spl_autoload_register(function ($className) {
echo ("from spl - 2:" . $className . PHP_EOL);
});
$notExist = new AnotherNotExist();
要点说明
- 方框1:
__autoload()
函数已不建议使用,推荐使用代码中的spl_autoload_register()
。__autoload()
的作用是引入没有找到的类,它接受的参数,即已知的条件是这个类的类名,所以引入的核心根据类名找到类文件所在目录,从而引入。为什么不使用__autoload()
呢,因为__autoload()
这个函数全局只能定义一次,如果都在里面定义类名和类文件目录的关系,这个函数将十分臃肿,因此 PHP5 开始建议使用spl_autoload_register()
进行注册。 - 方框2:当访问不存在的类时,可以看到,走到了
spl_autoload_register()
函数(方框 2 输出了想要访问的类名)。因为代码中既有spl_autoload_register()
,也有__autoload()
所以只访问了spl_autoload_register()
,只有__autoload()
时就会访问__autoload()
。
本作品采用《CC 协议》,转载必须注明作者和本文链接
composer 支持的加载规则 psr-0 psr-4 手动map,还有什么来着
从
vendor/autoload.php
开始看。