开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第一阶段:类的加载(spl 注册自动加载)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/711/detail/12672
类的加载(spl 注册自动加载)
内容介绍:
一、spl_autoload_register
一、spl_autoload_register
1.spl 注册自动加载的理论讲解
继续讲解一种高版本的,也就是推荐的自动加载的方式,spl_autoload_register 即注册自定义的函数,本质与 __autoload 一样,但是还是有区别的.
如果要实现加载,就需要定义一个函数。
请看以下一部分代码:
#定义一个函数,用来加载类文件
function my_autoload($classname){ #也需要一个参数来接收要加载的类名字
#功能与autoload()一样
$c_file='c/'.$classname .'. php' ; #如c/Saler.php
if(file_exists($c_file)){
include_once $cfile;
return true;
}
#说明 c 文件夹没有对应的文件
$m_file = ‘m/’ . $classname . ‘.php’; #如m/saler.php
If(file_exsits($m_file)){
Include_once $m_file;
Return true;
}
}
此时,上述函数永远不会自动运行,除非将函数注册到系统内部
假设当前需要做的和上述一致,判定目录然后实现加载,即不存在就实现加载,存在就不加载。
需要注意的是,,因为使用的是 once,所以这里判定的是文件是否存在,即文件不存在就加载,存在就不加载。而且这个函数是不会变形的。
2. spl 注册自动加载的运行演示
(1)写入13sp1_autoload.php函数,让其运行,如图:
可以看到,这里显示无法访问。
保存 13spl_autoload.php,然后确定保存成功。
如图:
利用自定义函数注册自动加载机制,因为当前没有机制,也没有所谓的 C 目录和 M 目录,需要做到自定义函数实现加载类
请看以下代码:
function my_autoload($classname){
#直接加载
if(class_exists($classname)){
#内存不存在,尝试加载
Include $classname · ‘.php’;
}
}
以上就是自定义的函数,可以看到,这里加载的类是 classname,,如果存在就不加载,不存在就加载类。
(2)尝试运行代码,即在代码后加上:
#实例化类
$s = new Saler();
运行,如图:
可以看到,这里显示类不存在,函数没有被触发,即自定义函数不会被系统触发。
(3)解决这个问题,可以在代码中添加一行:#将自定义函数注册到自动加载机制中,让自动加载能够执行
spl_autoload_register(‘my_autoload’);
如图:
可以看到,my_autoload 就是一个回调函数,系统内部提供一个名字再加上一个括号当作是函数调用。
如图,刷新页面:
可以看到,此时已经实现了自动加载而且没有报错,也因此,系统更愿意使用这种方式。
在代码后面再加上:$b = new Buyer();
如图:
然后运行,如图:
可以看到,这种方式也是可以实现的。
(4)对于不存在的文件,是无法实现加载的
如图:
在代码后加上:$a = new A() ;
运行后,如图:
可以看到,由于没有 A 这个文件存在,虽然机器不会拒绝访问,但是也无法找到 ’A.php’ 这个文件。这也说明之前的函数代码还未完善。
将原来代码改成:
function my_autoload($classname){
#直接加载
if(class_exists($classname)){
#内存不存在,尝试加载
$file = $classname . ‘.php’;
If(file_exists($file))include $file;
}
如图:
可以看到,如果这个文件存在,才能尝试去加载,不存在就不加载。
如图:
可以看到,此时不会出现 Warning 错误,但是无法解决无法找到类的问题。所以,自动加载并不是能够自动创建,而是帮助用户寻找文件。
以上就是利用 spl_autoload_register 实现加载的过程。
(5)spl_autoload_register 本质上就是通过自定义函数加上注册完成 __autoload 一样的操作,只是这种方式可以自定义多次加载函数。
比如说:c_autoload 是专门加载 c 的、而 m_autoload 是专门加载 m 目录下的;如果需要加载 n 个目录,就可以自定义 n 个函数然后把它们放进去,这样可以实现多个放在里面。
而对于系统的调用,如:
#全部注册
spl_autoload_register(’ c_autoload’);
spl_autoload_register(’ m_autoload’);
它的调用过程是先调用第一个注册的,再调用第二个注册的,如果都找不到,就不需要再去加载;如果找到了,比如说第一个找到了目录,那么第二个就不会再调用。
写入14sp1_autoload.php函数,让其运行
保存后,还需要:
#自定义自动加载,多个自动加载函数
请看以下代码:
function my_autoload($classname){
#直接加载
if(class_exists($classname)){
#内存不存在,尝试加载
$file = $classname . ‘.php’;
If(file_exists($file))include $file;
}
}
这段代码的逻辑是判断是否存在,如果存在就不加载,不存在就加载。
在代码下定义同样的函数,也就形成以下代码:
function c_autoload($classname){
if(!class_exists($classname)){
#内存不存在,尝试加载
$file = $classname . ‘.php’;
If(file_exists($file)) include $file;
}
}
function m_autoload($classname){
if(!class_exists($classname)){
#内存不存在,尝试加载
$file = $classname . ‘.php’;
If(file_exists($file)) include $file;
}
}
#注册
spl_autoload_register(‘c_autoload’);
spl_autoload_register(‘m_autoload’);
可以看到,代码最后注册了两个函数,接下来需要看类的第一个运行的是什么,查看的方式是在代码中加上:
echo__FUNCTION__,’<br>’;
如图:
以及加上:
#实例化不存在的类
$a = new A() ;
然后运行,如图:
可以看到,c_autoload 和 m_autoload 也就是两个函数都运行了,而且因为 c 先注册,所以 c 在前面。
然后再输入:
$s = new Buyer();
可以确定的是这里的第一个类一定能找到,因为它就是在当前目录里寻找。这里需要证明的是 m_autoload 这个函数是否会运行。
如图:
进行刷新,会发现 c_autoload 运行找到后,m_autoload 并没有运行。
所以,自动加载机制有一个特性,那就是:不管有多少个函数,只要有一个函数找到了,后面的函数就不会再运行了。这也是它内部的机制处理














