关于类的自动加载

June 06 , 2017

关于类的自动加载

@(PHP)[自动加载, 面试问题,每天进步一点]

[TOC]

休假结束了,最近开始找工作了,发现几个月不去碰电脑感觉好多东西都忘记了,面试的时候经常感觉知道一部分,但是印象很模糊,明明都有看过一些相关的资料。这里开始整理每天碰到的一些薄弱的知识点,加强下基础。

为什么要自动加载

在编写面向对象(OOP)程序时,很多开发者为每一个类新建一个PHP文件。这会带来一个烦恼:每个脚本的开头,都需要包含(include)一个常常的列表(每个类都有个文件)。

上面这段话是引用php官方的说法,有兴趣可以看看官方是怎么解释的。http://php.net/manual/zh/language.oop5.autoload.php

类的自动加载就是为了解决和简化这个问题的。

最常规的方式

在PHP5之前,各个框架如果要实现类的自动加载,一般都是按照自己约定好的规则去遍历目录,然后就如上面所说的,使用include,include_once,requice,requice_one进行常规加载。

假设有个类文件MyClassA.php,里面定义了一个名字是MyClassA的类:

MyClassA {
    public function __construct() {
        echo 'construct it!';
    }
}

然后有个入口的文件index.php需要加载这个类,最常规的写法就是

require('MyClassA.php');
$myClassA = new MyClassA();

那么如果我们有很多这种类似的文件,那就有很多的require,这样会很不爽。

__autoload

在PHP 5.0 至 5.1.2版本之间都是用的这个函数进行自动加载。

先看看官方的说明http://php.net/manual/zh/function.autoload.php

__autoload — 尝试加载未定义的类

Warning : This feature has been DEPRECATED as of PHP 7.2.0. Relying on this feature is highly discouraged.

那么可以知道这个函数可以尝试加载未定义的类,然后有个警告,说这个函数在未来的PHP 7.2.0版本后会被弃用,最好不用这个功能,那就说明是有缺陷的。

函数的使用方式:

void __autoload (string $class)

这里的参数class是带加载的类名,函数没有返回值。

还是用上面的类举例:

function __autoload($class) {
    $file = $class . '.php';
    if (is_file($file)) {
        require_once($file);
    }
}
$myClassA = new MyClassA();

我们可以看出__autoload至少要做三件事情 1.根据参数的类名确定文件名 2.找到这个文件所在的路径 3.加载这个文件

发现问题

__autoload确实可以成功的实现自动加载的功能。

问题在于文件路径的规则约定,类名的规则约定,如果一个项目很大,有很多第三方的文件,那么大家的类名和实际的磁盘文件映射规则都不相同,__autoload又只能定义一次,我们就必须将每一个规则都写在这个函数中,因此__autoload后期可能会非常的臃肿,复杂,甚至可能无法区维护。

这就是为什么官方会给出这个函数的警告提示了,那么我们应该怎么去更好的解决这个问题呢?php5.1.2之后给出了新的函数spl_autoload_register去更好的实现自动加载。

spl_autoload_register

官方的说明http://php.net/manual/zh/function.spl-autoload-register.php

spl_autoload_register — 注册给定的函数作为 __autoload 的实现

函数的使用方式:

bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )

参数:

autoload_function 欲注册的自动装载函数。如果没有提供任何参数,则自动注册 autoload 的默认实现函数spl_autoload()。

throw 此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。

prepend 如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。

返回值: 成功时返回 TRUE, 或者在失败时返回 FALSE。

spl_autoload_register('autoload_1');

function autoload_1($class_name)
{
    require_once $class_name . '.php';
}

$myClassA = new MyClassA();

根据官方的说法这个spl_autoload_register 它实际上创建了 autoload 函数的队列,按定义时的顺序逐个执行。相比之下, __autoload 只可以定义一次。而且如果第三方的类中用到了spl_autoload_register会使你的__autoload 失效

最后看下ThinkPHP中的使用 首先在入口文件中看到了

Alt text

接下来看看ThinkPHP.php,有个应用初始化的start方法

Alt text

继续看看start方法,看到了spl_autoload_register函数的使用,还有对应的autoload实现的方式。 Alt text

Alt text

结尾

面试能学到很多东西,知道自己哪些知识点不足,有不会的没关系,技术大神也是日积月累的,记下来马上去学习巩固就行。 多看看开源的框架,能发现有很多设计的思想和编码的方式值得学习。

发表评论

(请不要填写空的评论)
提交评论 使用QQ登录