PHP 自动加载机制的实现

前言

现在很多php框架都使用了命名空间来实现autoloader自动加载机制,配合编辑器的自动use避免了平凡include文件,开发起来十分方便,之前自己尝试写框架时候也使用到了autoloader机制,这里特意记录下.

实现过程

php有个__autoload() 函数,实现了在加载一个文件失败后尝试调用__autoload() 函数进行最后一次加载,因此通过一个有规律的命名规则就可以实现简单的自动加载机制

<?php
//实现自动加载当前目录下以类名命名的所有文件
function __autoload(classname) {filename = "./". classname .".php";
    include_once(filename);
}
$obj = new myClass();
?>

这种方式的缺点也显而易见,__autoload() 只能注册一个,如果项目有引用其他模块并且也使用到了__autoload() 就有冲突了,这个时候就需要使用spl_autoload_register 来注册自己的autoload方法

升级版

<?php

/**
 * 自动载入
 * Class autoloader
 */
class autoloader
{

    private static class_map = array();  //namespace => dir


    public function __construct()
    {
        spl_autoload_register('self::my_autoload');  //or spl_autoload_register(array('autoloader', 'my_autoload'));
    }

    private function my_autoload(class)
    {
        filename = self::getfilename(class);
        include filename;
    }

    //根据命名空间获得文件路径
    private static function getfilename(namespace)
    {
        name_paths = explode('\\',namespace);
        if (!isset(self::class_map[name_paths[0]])) {
            exit("`{name_paths[0]}` 命名空间未注册,请使用addClassMap注册");
        } else {filename = self::class_map[name_paths[0]] . '/';
            unset(name_paths[0]);filename .= implode('/', name_paths);
        }
        returnfilename . '.php';
    }


    public static function addClassMap(namespace,dir)
    {
        self::class_map[namespace] = dir;
    }

    public static function getClassMap()
    {
        return self::class_map;
    }
}

只需要在程序入口处引入此文件,就可以实现对其他文件的自动载入,如下

<?php
use Test\Image;

include 'autoloader.php';

autoloader = new \autoloader();autoloader->addClassMap('Test', './Test');  //注册命名空间,路径是相当于当前目录,而不是autoloader.php

$a = new Image();

其中命名空间注册只需要对顶级目录进行注册后,就可以对所有子目录下的文件实现自动加载,namespace的命名规则必须与目录和文件的命名一一对应

如文件在Test目录下,那么namespace 为 Test,class为Image,那么使用时就是

use Test\Image; 
$image=  new Image();

或者

$image = new \Test\Image();

 

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注