[TOC]
* * * * *
# 1 自动加载意义
> php的自动加载实现运行时**类的自动加载**。
> php的自动加载主要实现**类名到类文件的映射**
> 类名通常由**命名空间与类名组成**
> 文件通常由**基于特定目录的路径表明**
# 2 自动加载基础
## 2.1 __autoload()
> php5中,定义了__autoload()函数。运行时使用未被定义的类时,自动调用此函数,查找类的定义文件
~~~
<?php
function __autoload ( $class_name ) {
require_once $class_name . '.php' ;
}
$obj = new MyClass1 ();
$obj2 = new MyClass2 ();
?>
~~~
上面例子中,会自动加载MyClass1.php和MyClass2.php文件,其中定义了对应的MyClass1和MyClass2类。
## 2.2 spl_autoload()
> spl_autoload()作为__autoload()的默认实现。默认情况下将类名转换成小写,在小写的类名后面加上.ini或.php的扩展名作为文件名,然后在所有的包含路径中查找该文件。
## 2.3 spl_autoload_register()
> spl_autoload_register注册给定的函数作为__autoload的实现。
~~~
<?php
function my_autoloader ( $class ) {
include 'classes/' . $class . '.class.php' ;
}
spl_autoload_register ( 'my_autoloader' );
// 或者,自 PHP 5.3.0 起可以使用一个匿名函数
spl_autoload_register (function ( $class ) {
include 'classes/' . $class . '.class.php' ;
});
?>
~~~
spl_autoload_register()函数是使用最为广泛的自动加载实现。
# 3 Loader类自动加载
> think5的自动加载包括Loader类和composer自动加载两种机制。
> Loader类是think5实现的自动加载类
> Loader类的自动加载包含**类的注册,加载类的缓存,类的查找,常用类的自动实例化四部分**。
> composer是通用的自动加载实现
> composer包含**namespaces,classmap,files,psr4四种加载机制**。
## 3.1 Loader类
> Loader类在thinkphp\library\think\Loader.php文件
## 3.2 Loader类信息缓存
~~~
// 实例化对象缓存
protected static $instance = [];
// 类名映射
protected static $map = [];
// 命名空间别名
protected static $namespaceAlias = [];
// PSR-4
private static $prefixLengthsPsr4 = [];
private static $prefixDirsPsr4 = [];
private static $fallbackDirsPsr4 = [];
// PSR-0
private static $prefixesPsr0 = [];
private static $fallbackDirsPsr0 = [];
// 自动加载的文件
private static $autoloadFiles = [];
~~~
## 3.3 Loader类注册
### 1 addNamespace()
`public static function addNamespace($namespace, $path = '')`
> 注册命名空间到目录的映射关系
~~~
// 注册mynamespace与library/mynamespace/目录的映射关系
// 当使用mynamespace/Myclass类时,会自动在library/mynamespace/目录下查找Myclass文件
Loader::addNamespace('mynamespace',LIB_PATH.'mynamespace'.DS);
~~~
~~~
//注册thinknamespace的命名空间关系
$thinknamespace = [
'think' => LIB_PATH . 'think' . DS,
'behavior' => LIB_PATH . 'behavior' . DS,
'traits' => LIB_PATH . 'traits' . DS,
];
Loader::addNamespace($thinknamespae);
~~~
### 2 addClassMap()
`public static function addClassMap($class, $map = '')`
> 注册类到单个文件的映射关系
~~~
//注册Test类与application\other\test.php文件的对应关系
//使用Test类时Loader会自动加载application\other\test.php文件
Loader::addClassMap('Test',APP_PATH.'other\test');
~~~
~~~
//注册MyClass1与MyClass2的与对应文件关系。
$classMap = [
'MyClass1' => APP_PATH.'other\MyClass1',
'MyClass2' => APP_PATH.'other\MyClass2'
];
Loader::addClassMap($classMap);
~~~
### 3 addNamespaceAlias()
`public static function addNamespaceAlias($namespace, $original = '')`
>注册命名空间的别名,
>查找$namespace会自动查找$original命名空间
### 4 addPsr0()
`private static function addPsr0($prefix, $paths, $prepend = false)`
> 注册psr0规则自动加载机制
### 5 addPsr4()
`private static function addPsr4($prefix, $paths, $prepend = false)`
> 注册psr4规则自动加载机制
## 3.4 Loader类查找
### 1 registe()
`public static function register($autoload = '')`
> 注册自动加载机制
> $autoload参数为自动加载函数,默认为Loader::autoload()
### 2 registerComposerLoader()
`private static function registerComposerLoader()`
> 自动注册composer自动加载机制,
> 在register()中检查目录VENDOR_PATH\composer\时,自动注册composer。
### 3 autoload()
`public static function autoload($class)`
> 自动加载$class类
### 4 findFile()
`private static function findFile($class)`
> 加载$class类对应的文件
> 主要查找三种文件映射机制,
> 首先think的classmap,
> 其次psr-4的文件映射,
> 最后psr-0的文件映射。
## 3.5 Loader类加载与对象实例化
### 1 import()
`public static function import($class, $baseUrl = '', $ext = EXT)`
> 导入$baseUrl下的以$ext为后缀的$class的文件
> 导入的文件会缓存到$_file中
### 2 model()
`public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common')`
> 实例化模型对象
> 实例化后的对象缓存在Loader::$instance数组中
### 3 controller()
`public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')`
> 实例化控制器对象
### 4 validate()
`public static function validate($name = '', $layer = 'validate', $appendSuffix = false, $common = 'common')`
> 实例化验证器对象,
> 实例化后的对象缓存在Loader::$instance数组中
### 5 db()
`public static function db($config = [])`
> 实例化Db对象
### 6 action()
`public static function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)`
> 远程调用控制器方法
## 3.6 Loader类其他功能
### 1 parseName()
`public static function parseName($name, $type = 0)`
> 命名风格转换
### 2 parseClass()
`public static function parseClass($module, $layer, $name, $appendSuffix = false)`
> 解析应用类的类名
### 3 clearInstance()
`public static function clearInstance()`
> 清空所有实例化的对象
### 4 __include_file()
> 限制include文件的作用域
### 5 __require_file()
> 限制require文件的作用域
# 4 Composer自动加载
## 1 Composer实现
> Composer是php的包管理机制的实现,类似node的npm,python的pypi
> Composer通常用来自动下载远程网络包文件,实现框架的扩展功能
> Composer还可以用来管理框架本地的类加载。
> Composer的实现通常在框架的vendor\comoser\目录中
> 其中包含autoload_classmap.php,autoload_files.php,autoload_namespaces.php,autoload_psr4.php,autoload_real.php,ClassLoader.php等文件
> ClassLoader.php实现composer类的自动加载,其他文件包含composer的自动加载的类注册
> 每次运行composer命令时,会根据composer.json文件中的autoload规则,自动更新composer对应下的文件。
## 2 autoload_classmap.php
~~~
;部分代码
//定位目录
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
//返回的类名与文件映射数组
//将类名映射到目录下的特定文件
return array(
'File_Iterator' => $vendorDir . '/phpunit/php-file-iterator/src/Iterator.php',
'File_Iterator_Facade' => $vendorDir . '/phpunit/php-file-iterator/src/Facade.php',
'File_Iterator_Factory' => $vendorDir . '/phpunit/php-file-iterator/src/Factory.php',
.......
);
~~~
## 3 autoload_files.php
~~~
;部分代码
//定位目录
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
//返回文件别名与文件路径的映射关系数组
return array(
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'72c97b53391125cae04082a81029f42d' => $vendorDir . '/topthink/think-testing/src/config.php',
'9e05116ddaa5b1d244b68c3993908acd' => $vendorDir . '/topthink/think-queue/src/config.php',
'ddc3cd2a04224f9638c5d0de6a69c7e3' => $vendorDir . '/topthink/think-migration/src/config.php',
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
);
~~~
## 4 autoload_namespaces.php
~~~
//定位目录
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
//返回命名空间到目录的映射数组
return array(
'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'),
);
~~~
## 5 autoload_psr4.php
~~~
//定位目录
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
//返回psr4规则映射
return array(
'think\\testing\\' => array($vendorDir . '/topthink/think-testing/src'),
'think\\sae\\' => array($vendorDir . '/topthink/think-sae/src'),
'think\\queue\\' => array($vendorDir . '/topthink/think-queue/src'),
);
~~~
## 6 autoload_real.php
> composer的自动加载实现
## 7 ClassLoader.php
> composer的自动加载类
# 5 自动加载应用
## 1 thinkphp\base.php
~~~
// 载入Loader类
require CORE_PATH . 'Loader.php';
// 注册自动加载
\think\Loader::register();
~~~
## 2 thinkphp\library\App.php
~~~
// App::run()
// 清空类的实例化
Loader::clearInstance();
// App::initCommon()
// 注册配置的命名空间映射
self::$namespace = $config['app_namespace'];
Loader::addNamespace($config['app_namespace'], APP_PATH);
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
//App::init()
// 加载应用或模块别名配置文件
if (is_file(CONF_PATH . $module . 'alias' . EXT)) {
Loader::addClassMap(include CONF_PATH . $module . 'alias' . EXT);
}
~~~
## 3 Class查找异常
> 通常Class查找失败,框架会抛出异常
~~~
//Class查找失败代码
PHP Fatal error:Class 'Think\Log' not found
~~~
> 解决办法
~~~
1 确定引入命名空间或者使用绝对命名空间
use think;
\think\Log::init()
2 引入命名空间依然失败,查找命名空间对应目录的文件
~~~
# 6 其他资料
[php的自动加载](http://www.kancloud.cn/zmwtp/tp5/119447)
[composer的使用](http://www.kancloud.cn/zmwtp/tp5/120009)
[Loader的分析](http://www.kancloud.cn/zmwtp/tp5/127348)
[Loader的对象实例化](http://www.kancloud.cn/zmwtp/tp5/120008)
- 更新记录
- 概述
- 文件索引
- 函数索引
- 章节格式
- 框架流程
- 前:章节说明
- 主:(index.php)入口
- 主:(start.php)框架引导
- 主:(App.php)应用启动
- 主:(App.php)应用调度
- C:(Controller.php)应用控制器
- M:(Model.php)数据模型
- V:(View.php)视图对象
- 附:(App.php)应用启动
- 附:(base.php)全局变量
- 附:(common.php)模式配置
- 附:(convention.php)全局配置
- 附:(Loader.php)自动加载器
- 附:(Build.php)自动生成
- 附:(Hook.php)监听回调
- 附:(Route.php)全局路由
- 附:(Response.php)数据输出
- 附:(Log.php)日志记录
- 附:(Exception.php)异常处理
- 框架工具
- 另:(helper.php)辅助函数
- 另:(Cache.php)数据缓存
- 另:(Cookie.php)cookie操作
- 另:(Console.php)控制台
- 另:(Debug.php)开发调试
- 另:(Error.php)错误处理
- 另:(Url.php)Url操作文件
- 另:(Loader.php)加载器实例化
- 另:(Input.php)数据输入
- 另:(Lang.php)语言包管理
- 另:(ORM.php)ORM基类
- 另:(Process.php)进程管理
- 另:(Session.php)session操作
- 另:(Template.php)模板解析
- 框架驱动
- D:(\config)配置解析
- D:(\controller)控制器扩展
- D:(\model)模型扩展
- D:(\db)数据库驱动
- D:(\view)模板解析
- D:(\template)模板标签库
- D:(\session)session驱动
- D:(\cache)缓存驱动
- D:(\console)控制台
- D:(\process)进程扩展
- T:(\traits)Trait目录
- D:(\exception)异常实现
- D:(\log)日志驱动
- 使用范例
- 服务器与框架的安装
- 控制器操作
- 数据模型操作
- 视图渲染控制
- MVC开发初探
- 模块开发
- 入口文件定义全局变量
- 运行模式开发
- 框架配置
- 自动生成应用
- 事件与插件注册
- 路由规则注册
- 输出控制
- 多种应用组织
- 综合应用
- tp框架整合后台auto架构快速开发
- 基础原理
- php默认全局变量
- php的魔术方法
- php命名空间
- php的自动加载
- php的composer
- php的反射
- php的trait机制
- php设计模式
- php的系统时区
- php的异常错误
- php的输出控制
- php的正则表达式
- php的闭包函数
- php的会话控制
- php的接口
- php的PDO
- php的字符串操作
- php的curl
- 框架心得
- 心:整体结构
- 心:配置详解
- 心:加载器详解
- 心:输入输出详解
- 心:url路由详解
- 心:模板详解
- 心:模型详解
- 心:日志详解
- 心:缓存详解
- 心:控制台详解
- 框架更新
- 4.20(验证类,助手函数)
- 4.27(新模型Model功能)
- 5.4(新数据库驱动)
- 7.28(自动加载)