自动加载spl_autoload_register.php

自动加载spl_autoload_register.php

php中的类自动加载机制,及一些框架的示例。主要根据psr-4规范来定义自动加载机制,这样,可以利用composer工具,自动加载。一般情况下,是不需要自己来注册类的自动加载方法。

关于psr规范:

第一份推荐规范PSR-0。第一份推荐标准被新发布的PSR-4替代了。 同样是实现类的自动加载机制。

PSR-4:自动加载器

PHP-FIG发布的第四个推荐规范就是描述一个标准的自动加载器。自动加载器的策略就是依赖PHP命名空间和文件系统目录结构查找并加载PHP类、接口和性状。定义顶级命令空间所对应的跟目录,然后

关键函数

spl_autoload_register

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

函数式加载

spl_autoload_register('autoloader');

function autoloader($classname){
    //加载实现逻辑
}

类形式:

spl_autoload_register([‘类名’,’静态方法’]);

spl_autoload_register([‘对象实例’,’方法’]);

class Loader {

    protected  static $instance = null;
    
    static function getInstance(){
        if (empty($instance)){
            self::$instance = new self();
        }
        return self::$instance ;
    }

    static function register(){
        $me = self::getInstance();
        spl_autoload_register([$me,'loadClass']);
    }
    function loadClass($classname){
        $classPath = dirname(__FILE__).'/lib/'.str_replace('_','/',$classname).'.php';

        if(file_exists($classPath)){
            include $classPath;
            return true;
        }else{
            // 交给注册的下一个自动加载器处理  ???需要核实
            return false;
        }
    }
}
//注册 该方法
Loader::register();

Typecho自动加载

<?php
/**
* 自动载入类
*/
public static function __autoLoad($className)
{
    @include_once str_replace(array('\\', '_'), '/', $className) . '.php';
}

public static function init()
{
    /** 设置自动载入函数 */
    spl_autoload_register(array('Typecho_Common', '__autoLoad'));

    /** 设置异常截获函数 */
    set_exception_handler(array('Typecho_Common', 'exceptionHandle'));
}

Thinkphp5.1

实现的有点复杂,还利用到了静态变量的缓存,而且register方法可以根据参数$autoload,灵活注册加载函数。还照顾到了composer,自动加载支持。

class Loader{

// 注册自动加载机制
    public static function register($autoload = '')
    {
        // 注册系统自动加载
        spl_autoload_register($autoload ?: 'think\\Loader::autoload', true, true);

        $rootPath = self::getRootPath();

        self::$composerPath = $rootPath . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR;

        // Composer自动加载支持
        if (is_dir(self::$composerPath)) {
            if (is_file(self::$composerPath . 'autoload_static.php')) {
                require self::$composerPath . 'autoload_static.php';

                $declaredClass = get_declared_classes();
                $composerClass = array_pop($declaredClass);

                foreach (['prefixLengthsPsr4', 'prefixDirsPsr4', 'fallbackDirsPsr4', 'prefixesPsr0', 'fallbackDirsPsr0', 'classMap', 'files'] as $attr) {
                    if (property_exists($composerClass, $attr)) {
                        self::${$attr} = $composerClass::${$attr};
                    }
                }
            } else {
                self::registerComposerLoader(self::$composerPath);
            }
        }
        
       	
       	// 自动加载
    public static function autoload($class)
    {
        if (isset(self::$classAlias[$class])) {
            return class_alias(self::$classAlias[$class], $class);
        }

        if ($file = self::findFile($class)) {

            // Win环境严格区分大小写
            if (strpos(PHP_OS, 'WIN') !== false && pathinfo($file, PATHINFO_FILENAME) != pathinfo(realpath($file), PATHINFO_FILENAME)) {
                return false;
            }

            __include_file($file);
            return true;
        }
    }
}



// 注册自动加载
Loader::register();

Zendframework 1

其也有自动加载规范。

传统的类加载方式

参见brophp中的实现,核心set_include_path跟__autoload函数。这种跟zendframe1框架,有点像。算是一种比较简单的加载,但是,这种方式已经不推荐呢。

<?php
    //设置包含目录(类所在的全部目录),  PATH_SEPARATOR 分隔符号 Linux(:) Windows(;)
	$include_path=get_include_path();                         //原基目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."bases/";       //框架中基类所在的目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."classes/" ;    //框架中扩展类的目录
	$include_path.=PATH_SEPARATOR.BROPHP_PATH."libs/" ;       //模板Smarty所在的目录
	$include_path.=PATH_SEPARATOR.PROJECT_PATH."classes/";    //项目中用的到的工具类
	$controlerpath=PROJECT_PATH."runtime/controls/".TMPPATH;  //生成控制器所在的路径
	$include_path.=PATH_SEPARATOR.$controlerpath;             //当前应用的控制类所在的目录 

	//设置include包含文件所在的所有目录	
	set_include_path($include_path);

	//自动加载类 	
	function __autoload($className){
		if($className=="memcache"){        //如果是系统的Memcache类则不包含
			return;
		}else if($className=="Smarty"){    //如果类名是Smarty类,则直接包含
			include "Smarty.class.php";
		}else{                             //如果是其他类,将类名转为小写
			include strtolower($className).".class.php";	
		}
		Debug::addmsg("<b> $className </b>类", 1);  //在debug中显示自动包含的类
	}