「在PHP中,自定义类加载器」

内容:主要介绍类文件的自动加载;

看了德问社区的一个类似问题:http://www.dewen.net.cn/q/9824

文档中关于类自动加载的说明:http://php.net/manual/zh/language.oop5.autoload.php

使用__autoload方法

http://php.net/manual/en/function.autoload.php

void __autoload ( string $class )

如果类不存在会自动调用autoload($class)方法,通常 autoload() 需要开发者自己实现;

注意事项
就目前(03/06/2017)来讲,根据官方文档的描述不再建议使用__autoload()函数。因为这个不灵活,不过依然包含在PHP7中,建议使用spl_autoload_register;

使用spl_autoload_register方法

http://php.net/manual/en/function.spl-autoload-register.php

spl_autoload_register() 提供了一种更加灵活的方式来实现类的自动加载。因此,不再建议使用autoload()函数,在以后的版本中autoload()函数可能被弃用。

当类不存在的时候会自动加载“注册方法”,Demo:

<?php

// register 方法需要开发者自己实现;
function my_autoloader($class) {
    include 'classes/' . $class . '.class.php';
}

spl_autoload_register('my_autoloader');

但是实际中,我不是这么用的,我的类加载器使用了 spl_autoload 方法。

使用spl_autoload方法

http://php.net/manual/en/function.spl-autoload.php

function spl_autoload ($class_name, $file_extensions = null) {}

在默认情况下,本函数先将类名转换成小写,再在小写的类名后加上 .inc 或 .php 的扩展名作为文件名,然后在 include paths 中检查是否存在该文件。(有的时候你会发现php真的很php。怪不得类名那么奇怪。);

我的类加载器:

<?php
// 已省略部分非核心代码;

// register
function mClassLoader($class){
    $classFilename = preg_replace('/([a-zA-z]*\\\)/u', '', $class);//抹掉命名空间:)
    // set_include_path(ROOT_PATH . '/includes/class' );
    set_include_path(get_include_path() . PATH_SEPARATOR . ROOT_PATH . '/includes/class' );// get_include_path() 是为了取到原有的加载路径;
    spl_autoload_extensions('.class.php');// 设置 类文件文件的扩展名;
    spl_autoload($classFilename);// 加载类;
}

spl_autoload_register('mClassLoader');// 注册类加载器;

注意事项
有一点还是要强调一下,spl_autoload是先将“类名转小写”,再“拼接扩展名”,得到文件名,然后在 include paths 中检查是否存在该文件。

所以,如果你的“类文件名”是大写的,他是找不到的。这也是为什么 thinkphp3.2 解决这个问题的办法似乎就是不用spl_autoload方法,而是直接 require 类文件。