果冻想
认真玩技术的地方

PHP基础学习之autoload机制

前言

经过OOP(面向对象开发模式)的熏陶和洗礼。在我们开发时,大体上都会每一个类建立一个文件,这样也方便后期的扩展和维护,代码结构也非常清晰。然后在需要调用的时候,再通过include _once或者require_once将对应的类加载进来。

PHP5之前的日子

在还没有autoload的时候,就像我上面说的,在需要调用的时候,再通过include _once或者require_once将对应的类加载进来。比如现在有三个PHP文件:A.class.php、B.class.php和Main.cpp。A.class.php文件中的内容如下:

<?php
class A {
    function __construct () 
    { 
        var_dump('construct A');
    } 
}

B.class.php文件中的内容如下:

<?php
class B {
    function __construct () 
    { 
        var_dump('construct B');
    } 
}

Main.cpp文件中的内容如下:

<?php
require_once('A.class.php');
require_once('B.class.php');

new A();
new B();

在PHP5之前的日子,如果我们需要调用类A或者类B,就需要通过require_once的方式将A.class.php或者B.class.php文件加载进来,就像上面的Main.cpp文件那样。

这样使用从功能上来说是没有任何问题的。但是随着项目规模的不断扩大,使用这种方式会带来一些隐含的问题:如果一个PHP文件需要使用很多其它类,那么就需要很多的require/include语句,这样有可能会造成遗漏或者包含进不必要的类文件。如果大量的文件都需要使用其它的类,那么要保证每个文件都包含正确的类文件肯定是一个噩梦。

autoload来的日子

PHP5为这个问题提供了一个解决方案,这就是类的自动装载(autoload)机制。autoload机制可以使得PHP程序有可能在使用类时才自动包含类文件,而不是一开始就将所有的类文件include进来,这种机制也称为lazy loading

autoload机制的重点在于实现__autoload函数。当加载PHP类时,如果类所在文件没有被包含进来,或者类名出错,Zend引擎会自动调用__autoload函数。那现在的重点就是实现__autoload函数。一般我们在实现__autoload函数时,至少要完成以下三件事情:

  1. 根据类名确定类文件名;
  2. 确定类文件所在的磁盘路径;
  3. 将类从磁盘文件中加载到系统中。

为了方便确定类文件名,我们命名类文件时都需要遵守一定的规则,比如我上面的类A和类B都是按照xxx.class.php方式进行命名的。

下面通过代码来说明如何使用autoload机制。

<?php

function __autoload($className) {
    var_dump('__autoload called');
    $fileName = $className . '.class.php';

    if (file_exists($fileName)) {    
        require_once($fileName);     
    }
}

new A();
new B();

通过autoload机制实现的Main.php文件如上,现在我们并没有把每个PHP类文件都require_once一遍,而是实现了__autoload方法,这样在new A()时,程序发现找不到类A,这个时候引擎就会去调用__autoload方法,在__autoload方法中,我们可以自定义我们自己的实现逻辑。

未来的日子

__autoload出来后,社区一片欢呼,这东西确实好用,至少解决了频繁require_once的麻烦。但是随着开源社区牛人提供的公共库越来越多,这些类库可能是由不同的开发人员编写的,其类名与实际的磁盘文件的映射规则不尽相同。这时如果要实现类库文件的自动加载,就必须在_autoload()函数中将所有的映射规则全部实现,这样的话__autoload()函数有可能会非常复杂,甚至无法实现。最后可能会导致__autoload()函数十分臃肿,这时即便能够实现,也会给将来的维护和系统效率带来很大的负面影响。

那么问题出现在哪里呢?问题出现在__autoload()是全局函数只能定义一次,不够灵活,所以所有的类名与文件名对应的逻辑规则都要在一个函数里面实现,造成这个函数的臃肿。那么如何来解决这个问题呢?答案就是使用一个__autoload调用堆栈,不同的映射关系写到不同的__autoload函数中去,然后统一注册统一管理,这个就是PHP5引入的SPL Autoload。

后续的文章会继续总结关于SPL Autoload的内容。

总结

在写业务代码的日志里,很多时候我们都不会去在意这些东西,就很容易忽略这些东西;直到有一天看到了这些被我们忽略的东西,才发现自己除了增、删、改、查,其它的基本都忘了。高楼大厦离不开坚实的地基,后续的PHP查缺补漏系列会陆续推出一些我们不关注的知识点,让我们的开发工作更从容。

果冻想-一个原创技术文章分享网站。

2018年2月4日 于呼和浩特。

未经允许不得转载:果冻想 » PHP基础学习之autoload机制
网站维护离不开您的支持,您可以赞助本站,谢谢支持
×

感谢您的支持,我们会一直保持!

扫码支持
请土豪扫码随意打赏

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

赞助本站
关注微信公众号
关注微信公众号和果冻一起分享你的疑惑与心得。
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

玩技术,我们是认真的

联系我们关于果冻