一、自动加载的由来与使用
a.通常php的加载是通过include(),require()等方法来加载外部文件,之后再通过实例调用方法或直接调用静态方法,而这样子写引入语句实在很麻烦;
b.有的框架会将特定路径的文件全部引入,直接实例化就能使用,但这样一来有的类包不一定用到,写的类包越多的时候,加载的东西就不少了,影响程序的性能。
此时,懒加载闪亮登场了!
懒加载:实例化一个ReflectionClass,并传类名进去,就会得到一个对应类的反射类。用实例调用newInstance就会得到反射类的实例,这样就完成了实例化。
2个例子:
|
实例化一个 ReflectionClass,并传类名进去,就会得到一个对应类的反射类。用实例调用 newInstance就会得到反射类的实例,这样就完成了实例化。通过 get_included_files() 方法,我们可以看到当前页面引入的文件。在实例化反射类前,只有index.php文件,实例化反射类后,自动引入了一个test.php文件,那么看下上面那段代码,发现有个__autoload()名字的魔术方法,这方法就定义了自动加载文件,而ReflectionClass在当前页面找不到类时,就会调用__autoload()去加载类。这就是自动加载的过程。
|
sql_autoload_functions() 方法是用来查看当前自动加载的方法,当前有个__autoload魔术方法,所以返回了函数名,若没定义自动加载方法的话,返回的是false,而 spl_autoload_register() 方法是通过方法名将一个方法注册到自动加载方法,这里用newAutoload方法来替换__autoload方法。newAutoload方法中,每执行成功一次,打印一句'require success',这里只打印了一次,说明了虽然实例了3次ReflectionClass('test'),但因为test类已经加载过一次,就不会再执行自动加载的方法。通过getInstance()这种加载类的方法,比以前的include()之类的方便多了,只需要加载这个写了getInstance()方法的文件就可以了。
二、yii2自动加载的原理(spl_autoload_register函数)
(1)首先,引入了BaseYii.php文件,然后声明了类Yii,继承了BaseYii,然后注册了Yii(其实是BaseYii)的autoload方法,去实现自动加载。(2)之后,又引入了Yii核心类名与文件地址一一对应的Map,存储到Yii::$classMap中。(3)最后,创建了一个 yii\di\Container的实例,存储到Yii::$container中。源码解析详见:https://blog.csdn.net/lmjy102/article/details/70788484
三、composer的四种自动加载方式
四种加载方式:PSR-4(推荐)、PSR-0(不推荐)、classmap、files
首先,引入autoload.php,在主文件index.php中,
require 'vendor/autoload.php';
其次,composer.json的四种配置:
图2 |
|
图3 |
图4 |
(1)psr-4在composer.json里的配置见图1:执行composer install
更新自动加载,更新执行composer dump-autoload。照PSR-4的规则,当在index.php中试图new Foo\Bar\Baz
这个class时,composer会自动去寻找 "src/Bar/Baz.php" 这个文件,如果它存在则进行加载。
(2)psr-0在composer.json里的配置见图2:执行composer install
更新自动加载,更新执行composer dump-autoload。注意,照PSR-0的规则,当在index.php中试图new Foo\Bar\Baz
这个class时,composer会去寻找 "src/Foo/Bar/Baz.php" 这个文件,如果它存在则进行加载。
注意:PSR-4和PSR-0的配置里,"Foo\"结尾的命名空间分隔符必须加上并且进行转义,以防出现"Foo"匹配到了"FooBar"这样的意外发生。
(3)classmap在composer.json里的配置见图3:执行composer install
更新自动加载,更新执行composer dump-autoload。composer会扫描指定目录下以.php 或.inc 结尾的文件中的 class,生成 class 到指定 file path 的映射,并加入新生成的vendor/composer/autoload_classmap.php
文件中。 例如src/下有一个BaseController
类,那么在autoload_classmap.php
文件中,就会生成这样的配置:
'BaseController' => $baseDir . '/src/BaseController.php'
实例化类的方式这里有两种不同的情况。(1)如果加载的文件有命名空间,直接按命名空间实例化。(2)如果没有命名空间,直接按类名实例化。
(4)files在composer.json里的配置见图4:执行composer install
更新自动加载,更新执行composer dump-autoload。Files方式,就是手动指定供直接加载的文件。比如说我们有一系列全局的helper functions,可以放到一个helper文件里然后直接进行加载,也就是说,当你用require 'vendor/autoload.php';
加载自动加载类时自动将files里的文件加载进来了,你直接使用就行了。