深入理解 spl_autoload , __autoload 以及 spl_autoload_register

这篇文章将从初学者到进阶同学的角度,循序渐进的谈论一下 PHP 中的自动加载类,以及深入理解 spl_autoload , __autoload ,spl_autoload_register。


什么是加载

学过java 或者c的同学都知道,要在一个文件中使用另一个文件所定义的类,java是通过import实现的,而c是通过include 头文件实现的,相对来说都简单,同样,在PHP中也有类似这样的机制,你也可以在前面使用include 或者include_once 等等的手段来加载其他类的文件。

除此以外,PHP还有一个自动加载类机制,如果说PHP找不到类的定义(比如说你在A.class.php 中想要new 一个B 类),就会触发自动加载类。

自动加载类之 __autoload

直接上例子

本例尝试分别从 MyClass1.php 和 MyClass2.php 文件中加载 MyClass1 和 MyClass2 类。

<?php
spl_autoload_register(function ($class_name) {
    include $class_name . '.php';
});

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>

直接拿来用

在实际开发中,如果我们要使用自动加载类,通常代码是这样

<?php 
//Define autoloader 
function __autoload($className) { 
      if (file_exists($className . '.php')) { 
          require_once $className . '.php'; 
          return true; 
      } 
      return false; 
} 

function canClassBeAutloaded($className) { 
      return class_exists($className); 
} 
?>

面试题:如果非要说上面的代码有地方可以改进,你说说是哪里?

没有必要使用require_once 或者是 include_once,因为只有在类找不到的时候才会出发自动加载类。

再进一步

在英文的api中我们发现有这样一句话,

Whilst the __autoload() function can also be used for autoloading classes and interfaces, its preferred to use the spl_autoload_register() function. This is because it is a more flexible alternative (enabling for any number of autoloaders to be specified in the application, such as in third party libraries). For this reason, using __autoload() is discouraged and it may be deprecated in the future.

官方文档中更建议使用spl_autoload_register ,因为更加灵活,可以保证任意数量的自动加载类在项目中顺利运行,尤其是在使用第三方库。

这个说的并不是很明确,我再解释一下。

谈谈spl_autoload_register()

spl_autoload_register()

允许你注册多个方法,或者静态方法,PHP引擎会把他们放到栈/队列中,当你“new” 一个类的时候,会顺序的调用。

举个例子

spl_autoload_register('myAutoloader');

function myAutoloader($className)
{
    $path = '/path/to/class';

    include $path.$className.'.php';
}

//-------------------------------------

$myClass = new MyClass();

对于对于myAutoloader 来说,Myclass,就是一个字符串,所以说你可以对它为所欲为,比如说加后缀,有人喜欢.php,有人喜欢.class.php,你只要注册了自动加载类的方法,引擎就会自动调用,不用你在文件开头进行include声明。

用spl_autoload_register 的好处呢?

用spl_autoload_register 之后,你不需要在每一个类中都去重写__autoload方法,并且你可以注册多次

举个例子

spl_autoload_register('MyAutoloader::ClassLoader');
spl_autoload_register('MyAutoloader::LibraryLoader');
spl_autoload_register('MyAutoloader::HelperLoader');
spl_autoload_register('MyAutoloader::DatabaseLoader');

class MyAutoloader
{
    public static function ClassLoader($className)
    {
         //your loading logic here
    }


    public static function LibraryLoader($className)
    {
         //your loading logic here
    }

对于spl_autoload,简单来说就是__autoload 的默认实现,如果spl_autoload_register()在无参的情况下被调用,就会调用__autoload()。

补充几点,如果说你的所有的文件都放在同一个文件夹内,不仅仅是.php结尾的还有.inc结尾的用户配置文件,可以使用set_include_path()把所有需要的文件防盗php的include路径下,再通过spl_autoload_extensions()列出扩展,例子:

set_include_path(get_include_path().PATH_SEPARATOR.'path/to/my/directory/');
spl_autoload_extensions('.php, .inc');
spl_autoload_register();

参考:http://stackoverflow.com/questions/7651509/someone-explain-spl-autoload-autoload-and-spl-autoload-register

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值