PHP 自动加载
回顾
开始的时候, 如果想在一个php文件中使用其它文件的类或方法, 需要通过include/require方法将文件包含进来. 这种方法的缺点也很明显:
- 如果需要引入很多文件, 就需要很多的include语句, 不仅不美观, 而且也难免会又遗漏
- 如果多个文件中定义了相同名称的常量, 会导致抛出重复定义的警告
autoload
为了解决这个问题, 在PHP5中引入了自动加载的概念, 通过 __autoload 函数来实现, 如下:
function __autoload($classname){
// 完成 指定名称类的加载任务
include_once($classname.'.php')
}
将这个函数定义在文件中, 当遇到未引入的类时, 会调用此函数进行引入, 看起来貌似很好, 我们只需要将此函数定义在也给PHP文件中, 以后我们的每个文件就只需要引入这一个自动加载文件就可以了, 看起来完事大吉.
但通过使用, 这种方式也存在很多问题:
- 因为PHP不能出现同名函数, 所以当出现两个自动加载函数时, 会报错. 当然, 自己的项目可以保证, 但我们还是要引入第三方库的啊.
- 所有的函数映射都放到一个函数中, 势必造成函数的臃肿, 同时也不利于维护
很明显, 问题就出在了, 这是一个全局函数, 只能够定义一次,
spl_autoload
那么如何解决这个问题呢? PHP引入了一个扩展库, 可以定义多个自动加载函数, 在查找的时候会依次调用定义好的自动加载函数进行加载, 有如下方法:
- spl_autoload_register: 注册自动加载函数
- spl_autoload_unregister: 删除已注册的自动加载函数
- spl_autoload_functions: 获取所有注册的自动加载函数
- spl_autoload_call: 依次调用所有注册的自动加载函数进行加载
- spl_autoload: 自动加载函数的默认实现, 若没有进行注册, 默认调用此函数
- spl_autoload_extionsions: 注册并返回 spl_autoload 中使用的默认文件扩展名
有了它, 我们就可以定义多个自动加载函数了.
下面是一个例子:
test01.php
namespace test01;
class test{
public static function tt(){
echo 'test01';
}
}
test02.php
namespace test02;
class test{
public static function tt(){
echo 'test02';
}
}
run.php
spl_autoload_register(function ($classname){
include_once $classname.'01.php';
});
spl_autoload_register(function ($classname){
include_once $classname.'02.php';
});
use test01\test;
test::tt();
运行run.php, 报错:
Warning: include_once(test01\test01.php): failed to open stream: No such file or directory in
打印传入的 $classname, 发现是: test01\test
也就是说, 我们使用的时候可以将命名空间与路径相对应, 关于这个好像还有一个标准, 具体记不清了.
这样一对应, 有没有感觉和java中的包有些一样了, 反正我是觉得挺像.
composer
好了, 现在通过 composer来管理第三方库, 它将自动加载都做好了, 只要引入他的 autoload.php 文件就可以了.
composer提供了几种类型的自动加载
1.psr-4
大概就是我们上面说的路径和命名空间对应的形式
2. classmap
保存各个类与文件的映射map
等等吧, 没有具体研究, 不过大体是对自动加载的封装, 很方便.
简单总结一下, 才疏学浅..