自动加载的测试代码
https://github.com/bayuexiong/simple-composer
1. 自动加载
php的加载文件,一般分为三种情况
- 直接
include/require
,不属于自动加载,一般用于PHP5以前的版本。 - 使用
__autoload()
,PHP5.0引入,在PHP5.1.12之后不再推荐使用。 - 使用
spl_auoload_register()
,现在使用比较多,于PHP5.1.12之后加入,提供了一种更加灵活的方式加载文件。
具体实例
第一种没什么说的。主要还是看第二种和第三种。
假设在一个项目里面有两个文件
Demo.php
class Demo{# coding}
index.php
function __autoload($class_name){$file = dirname(__FILE__) . '/' . $class_name;if (file_exist($file)) {
include($file);
}
}
$obj = new Demo();
Demo.php
和index.php
只要在一个同级目录内,php变会很智能的加载Demo.php
,不需要显示的操作。
但是这里还是存在弊端的,比如一个项目中只能有一个__autoload()
,这也意味着自动加载的价值变得很低,于是PHP便在PHP5.1.12版本之后添加了spl_autoload_register()
,它接受一个回调函数,使得自动加载更加的灵活。
修改index.php
function my_autoload($class_name)
{
$file = dirname(__FILE__) . '/' . $class_name;
if (file_exist($file)) {
include($file);
}
}
spl_autoload_register('my_autoload');
$obj = new Demo();
之前的Demo.php
不做修改,将index.php
如此修改,便可以同样的功能。
关于spl_autoload_register()
更多的内容可以查看官方文档。
http://php.net/manual/zh/function.spl-autoload-register.php
注意类名和文件名必须保持一致!!!
2. Composer
在5.3之后,Composer大行其道,号称PHP未来的希望。。。
使用Composer自动加载时只要引入一个自动加载文件就可以了。
include_once('vendor/autoload.php');
那么Composer的自动加载时怎么实现的呢,其实也是依靠spl_autoload_register()
。
首先Composer存储三对数组
class=>dir
namespace=>array(dir, dir, dir)
PSR4=>array(dir, dir1, dir2...)
然后在autoload.php, 存在一个loader,可以触发spl_autoload_register,
一旦触发,Composer会对触发的类型进行分析,选择合适的数组,将真实的地址提取出来,然后include
,原理还是很简单,推荐大家自行查看一下Composer的自动加载的代码。
关于composer的一个Tips
在上线代码时可以使用
composer dump-autoload -o
转换PSR-0/4 autoloading
到classmap
获得更快的载入速度。这特别适用于生产环境,但可能需要一些时间来运行,因此它目前不是默认设置。至于为什么,看完源代码就清晰了。
3. 简单实现一个Composer自动加载
简单实现ClassMap的自动加载功能
https://github.com/bayuexiong/simple-composer/tree/master/vendor
使用代码和Composer一样。
include 'vendor/autoload.php';
$obj = new Demo('gg');
$obj->sayName();
$obj2 = new Other('aa');
$obj2->sayName();
4. 如何选择自动加载机制
- 在程序一开始运行的时候,使用数组,将项目内所有的文件记录下来,实现自动加载(如果使用cache,应该还hold的住),
symfony
使用这种形式,代码如下。
https://github.com/symfony/class-loader/blob/master/ClassMapGenerator.php - class名和路径对应,便于查找,但是这样缺乏灵活性,框架的侵入性太强了,代码很受框架的限制,像ThinkPHP,CI就是使用这种形式。
- 组合使用,像Laravel就是使用PSR4和symfony的classLoader。
5. CI框架的自动加载
现在公司使用CI框架的情况比较多,所以对CI框架的自动加载做一些详细的介绍。
对于一个普通的CI加载类的方式:
$this->load->library('myclass');
CI框架的内部是如何运行的呢?首先上个流程图
具体的实现可以查看源代码,都在system/core/Loader.php文件下面。
其实CI框架的自动加载并没有借助spl系列的函数,而是直接查找文件的方式来自动加载,这可能与CI框架诞生的年岁有关,在那个时期不失为一种优秀的自动加载方法。
但是现在来说,算不上优秀,其对命名的规范太过苛刻了,效率也谈不上高效,当然CI框架的整体速度还是很快的,毕竟像symfony
之流的框架为了实现完全解耦,付出了很多性能上的代价。
Tips
对于一个普通的加载类
$this->load->library($library, $param, $object_name);
1.$library
可以是一个数组key代表需要加载的类,value则是obejct_name。
2.$param
需要一个数组,作于传入构造器中的值
3.$object_name
和$this->load->model(calss, object_name)
中第二个参数一样,加载完之后可以$this->object_name->sayHello()
具体的可以结合CI的文档再加上阅读CI的源代码,的确CI的文档相比其他的框架比较全面,但是一些技巧也没有详尽的介绍。
6. 小结
使用Composer吧!使用RSP4命名空间规范吧!这样各个组件与组件之间,自己的代码和别人的代码都可以无痛的结合,不需要花费额外的精力去处理文件加载的问题。
7. 补充
材料参考: