[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.hmoore.net/zmwtp/tp5/119447)
[composer的使用](http://www.hmoore.net/zmwtp/tp5/120009)
[Loader的分析](http://www.hmoore.net/zmwtp/tp5/127348)
[Loader的對象實例化](http://www.hmoore.net/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(自動加載)