PHP 类的自动加载机制

2,237 阅读2分钟
原文链接: www.jianshu.com

我们在常见的PHP的框架如YII、TP中通常写好一个类只需写好相应的命名空间就可以实现类的使用。那么你知道为什么不再需要使用include文件了吗?框架是怎么帮你做到这个文件的引用的呢?其中的原理就是——类的自动加载。

如果没有自己写过MVC框架或者看过框架源码的同学就有可能不了解自动加载机制,还有可能会认为是php内核底层自动去实现的。其实,它的实现过程还是在php代码层。该机制涉及最核心是 spl_autoload_register 这个函数,下面通过解析Yii框架代码来说明它是怎么做到的。


Yii入口文件代码截图

上图是Yii入口文件中的两行代码,接下来我们找到对应目录下 Yii.php这个类,如下图:


Yii.php截图


在这个类里你马上就能看到spl_autoload_register这个方法了。其中有3个参数(['Yii','autoload'],true,true),第一个参其表示要调用的类和方法,即当遇到没有加载过的类时会调用Yii::autoload()这个方法。第二个参数和第三个参数分别表示注册失败是否抛出异常、将函数插到队列之首,后两个参数默认false我们可以先不关心。

依旧看上图中Yii类没有任何方法,只是继承了BaseYii,说明该方法来自继承的类中。进入到BaseYii搜索,果然有autoload()这个静态方法,代码如下图:


BaseYii::autoload()

该方法传入一个$className参数,文件的加载就是倒数第4行代码include($classFile);

那么一切都已经明了了,当PHP使用到找不到的类时,会调用spl_autoload_register注册的方法,将要未知的类名以$className作为参数传入该方法中,通过在这个方法写业务逻辑来找到指定的文件并加载。这个跟__get($name)是一个设计思想。这下,你该懂了吧。

接下来做个实验通过页面输入看看autoload中$className参数和$classFile是什么样子的。增加两行输出代码:


输出测试

随便运行一个页面,结果如下:


页面输入

可以看出$className就是待加载的包含命名空间的类名,$classFile就是这个类的文件地址。

到这里,自动加载的机制就算解析结束了。

顺便再说一下刚刚提到spl_autoload_register的第三个参数——将函数插到队列之首的含义。php还有个__autoload方法的也是用于自动加载的,但其有很多缺陷,它做为一个类函数有很大的局限性。而使用sql_autoload则可以在很多个地方进行使用,当使用多个spl_autoload_register方法是,php也会自动按顺序调用被注册的方法。而第三个参数则是控制将本次注册的方法放在队列的前面还是后面。