自动加载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中显示自动包含的类
}