ThinkPHP引入了全新的**CBD(核心Core+行為Behavior+驅動Driver)**架構模式,從底層開始,框架就采用核心+行為+驅動的架構體系,核心保留了最關鍵的部分,并在重要位置設置了標簽用以標記,其他功能都采用行為擴展和驅動的方式組合,開發人員可以根據自己的需要,對某個標簽位置進行行為擴展或者替換,就可以方便的定制框架底層,也可以在應用層添加自己的標簽位置和添加應用行為。而標簽位置類似于AOP概念中的“切面”,行為都是圍繞這個“切面”來進行編程。
## Core(核心)
ThinkPHP的核心部分包括核心函數庫、慣例配置、核心類庫(包括基礎類和內置驅動及核心行為),這些是ThinkPHP必不可少的部分。
~~~
ThinkPHP/Common/functions.php // 核心函數庫
ThinkPHP/Conf/convention.php // 慣例配置文件
ThinkPHP/Conf/debug.php // 慣例調試配置文件
ThinkPHP/Mode/common.php // 普通模式定義文件
ThinkPHP/Library/Think // 核心類庫包
ThinkPHP/Library/Behavior // 系統行為類庫
ThinkPHP/Library/Think/App.class.php // 核心應用類
ThinkPHP/Library/Think/Cache.class.php // 核心緩存類
ThinkPHP/Library/Think/Controller.class.php // 基礎控制器類
ThinkPHP/Library/Think/Db.class.php // 數據庫操作類
ThinkPHP/Library/Think/Dispatcher.class.php // URL解析調度類
ThinkPHP/Library/Think/Exception.class.php // 系統基礎異常類
ThinkPHP/Library/Think/Hook.class.php // 系統鉤子類
ThinkPHP/Library/Think/Log.class.php // 系統日志記錄類
ThinkPHP/Library/Think/Model.class.php // 系統基礎模型類
ThinkPHP/Library/Think/Route.class.php // 系統路由類
ThinkPHP/Library/Think/Storage.class.php // 系統存儲類
ThinkPHP/Library/Think/Template.class.php // 內置模板引擎類
ThinkPHP/Library/Think/Think.class.php // 系統引導類
ThinkPHP/Library/Think/View.class.php // 系統視圖類
~~~
Behavior目錄下面是系統內置的一些行為類庫,內置驅動則分布在各個不同的驅動目錄下面(參考下面的驅動部分)。
## Driver(驅動)
3.2版本在架構設計上更加強化了驅動的設計,替代了之前的引擎和模式擴展,并且改進了行為的設計,使得框架整體更加靈活,并且由于在需要寫入數據的功能類庫中都采用了驅動化的設計思想,所以使得新的框架能夠輕松滿足分布式部署的需求,對云平臺的支持可以更簡單的實現了。因此,在新版的擴展里面,已經取消了引擎擴展和模式擴展,改成配置不同的應用模式即可。
驅動包括
~~~
ThinkPHP/Library/Think/Cache/Driver // 緩存驅動類庫
ThinkPHP/Library/Think/Db/Driver // 數據庫驅動類庫
ThinkPHP/Library/Think/Log/Driver // 日志記錄驅動類庫
ThinkPHP/Library/Think/Session/Driver // Session驅動類庫
ThinkPHP/Library/Think/Storage/Driver // 存儲驅動類庫
ThinkPHP/Library/Think/Template/Driver // 第三方模板引擎驅動類庫
ThinkPHP/Library/Think/Template/TagLib // 內置模板引擎標簽庫擴展類庫
~~~
## Behavior(行為)
行為(Behavior)是ThinkPHP擴展機制中比較關鍵的一項擴展,行為既可以獨立調用,也可以綁定到某個標簽(位)中進行偵聽。這里的行為指的是一個比較抽象的概念,你可以想象成在應用執行過程中的一個動作或者處理,在框架的執行流程中,各個位置都可以有行為產生,例如路由檢測是一個行為,靜態緩存是一個行為,用戶權限檢測也是行為,大到業務邏輯,小到瀏覽器檢測、多語言檢測等等都可以當做是一個行為,甚至說你希望給你的網站用戶的第一次訪問彈出Hello,world!這些都可以看成是一種行為,行為的存在讓你無需改動框架和應用,而在外圍通過擴展或者配置來改變或者增加一些功能。
而不同的行為之間也具有位置共同性,比如,有些行為的作用位置都是在應用執行前,有些行為都是在模板輸出之后,我們把這些行為發生作用的位置稱之為**標簽(位)**,也可以稱之為鉤子,當應用程序運行到這個標簽的時候,就會被攔截下來,統一執行相關的行為,類似于AOP編程中的“切面”的概念,給某一個標簽綁定相關行為就成了一種類AOP編程的思想。
### 系統標簽位
系統核心提供的標簽位置包括(按照執行順序排列):
- app_init 應用初始化標簽位
- module_check 模塊檢測標簽位(**3.2.1版本新增**)
- path_info PATH_INFO檢測標簽位
- app_begin 應用開始標簽位
- action_name 操作方法名標簽位
- action_begin 控制器開始標簽位
- view_begin 視圖輸出開始標簽位
- view_template 視圖模板解析標簽位
- view_parse 視圖解析標簽位
- template_filter 模板解析過濾標簽位
- view_filter 視圖輸出過濾標簽位
- view_end 視圖輸出結束標簽位
- action_end 控制器結束標簽位
- app_end 應用結束標簽位
在每個標簽位置,可以配置多個行為,行為的執行順序按照定義的順序依次執行。除非前面的行為里面中斷執行了(某些行為可能需要中斷執行,例如檢測機器人或者非法執行行為),否則會繼續下一個行為的執行。
除了這些系統內置標簽之外,開發人員還可以在應用中添加自己的應用標簽,在任何需要攔截的位置添加如下代碼即可:
~~~
// 添加my_tag 標簽偵聽
\Think\Hook::listen('my_tag');
~~~
方法第一個參數是要偵聽的標簽位,除此之外還可以傳入并且只接受一個參數,如果需要傳入多個參數,請使用數組。
~~~
// 添加my_tag 標簽偵聽
\Think\Hook::listen('my_tag',$params);
~~~
該參數為引用傳值,所以只能傳入變量,因此下面的傳值是錯誤的:
~~~
// 添加my_tag 標簽偵聽
\Think\Hook::listen('my_tag','param');
~~~
### 核心行為
系統的很多核心功能也是采用行為擴展組裝的,對于滿足項目日益紛繁復雜的需求和定制底層框架提供了更多的方便和可能性。
核心行為位于 `ThinkPHP/Behavior/` 目錄下面,框架核心內置的行為包括如下:
| 行為名稱 | 說明 | 對應標簽位置 |
|-----|-----|-----|
| BuildLite | 生成Lite文件(3.2.1版本新增) | app_init |
| ParseTemplate | 模板文件解析,并支持第三方模板引擎驅動 | view_parse |
| ShowPageTrace | 頁面Trace功能行為,完成頁面Trace功能 | view_end |
| ShowRuntime | 運行時間顯示行為,完成運行時間顯示 | view_filter |
| TokenBuild | 令牌生成行為,完成表單令牌的自動生成 | view_filter |
| ReadHtmlCache | 讀取靜態緩存行為 | app_init |
| WriteHtmlCache | 生成靜態緩存行為 | view_filter |
### 行為定義
自定義的擴展行為可以放在核心或者應用目錄,只要遵循命名空間的定義規則即可。
行為類的命名采用:
> 行為名稱(駝峰法,首字母大寫)+Behavior
行為類的定義方式如下:
~~~
namespace Home\Behavior;
class TestBehavior {
// 行為擴展的執行入口必須是run
public function run(&$params){
if(C('TEST_PARAM')) {
echo 'RUNTEST BEHAVIOR '.$params;
}
}
}
~~~
行為類必須定義執行入口方法`run`,由于行為的調用機制影響,run方法不需要任何返回值,所有返回都通過引用返回。
> run方法的參數只允許一個,但可以傳入數組。
### 行為綁定
行為定義完成后,就需要綁定到某個標簽位置才能生效,否則是不會執行的。
我們需要在應用的行為定義文件`tags.php`文件中進行行為和標簽的位置定義,格式如下:
~~~
return array(
'標簽名稱1'=>array('行為名1','行為名2',...),
'標簽名稱2'=>array('行為名1','行為名2',...),
);
~~~
標簽名稱包括我們前面列出的系統標簽和應用中自己定義的標簽名稱,比如你需要在app_init標簽位置定義一個`CheckLangBehavior`行為類的話,可以使用:
~~~
return array(
'app_init'=>array('Home\Behavior\CheckLangBehavior'),
);
~~~
可以給一個標簽位定義多個行為,行為的執行順序就是定義的先后順序,例如:
~~~
return array(
'app_init'=>array(
'Home\Behavior\CheckLangBehavior',
'Home\Behavior\CronRunBehavior'
),
);
~~~
默認情況下tags.php中定義的行為會并入系統行為一起執行,也就是說如果系統的行為定義中app_init標簽中已經定義了其他行為,則會首先執行系統行為擴展中定義的行為,然后再執行項目行為中定義的行為。例如: 系統行為定義文件中定義了:
~~~
'app_begin' => array(
'Behavior\ReadHtmlCacheBehavior', // 讀取靜態緩存
),
~~~
而應用行為定義文件有定義:
~~~
'app_begin' => array(
'Home\Behavior\CheckModuleBehavior',
'Home\Behavior\CheckLangBehavior',
),
~~~
則最終執行到app_begin標簽(位)的時候,會依次執行:
~~~
Library\Behavior\ReadHtmlCacheBehavior
Home\Behavior\CheckModuleBehavior
Home\Behavior\CheckLangBehavior
~~~
三個行為(除非中間某個行為有中止執行的操作)。
如果希望應用的行為配置文件中的定義覆蓋系統的行為定義,可以改為為如下方式:
~~~
'app_begin' => array(
'Home\Behavior\CheckModuleBehavior',
'Home\Behavior\CheckLangBehavior',
'_overlay' => true,
),
~~~
則最終執行到app_begin標簽(位)的時候,會依次執行下面兩個行為:
~~~
Home\Behavior\CheckModuleBehavior
Home\Behavior\CheckLangBehavior
~~~
應用行為的定義沒有限制,你可以把一個行為綁定到多個標簽位置執行,例如:
~~~
return array(
'app_begin'=>array('Home\Behavior\TestBehavior'), // 在app_begin 標簽位添加Test行為
'app_end'=>array('Home\Behavior\TestBehavior'), // 在app_end 標簽位添加Test行為
);
~~~
### 單獨執行
行為的調用不一定要放到標簽才能調用,如果需要的話,我們可以在控制器中或者其他地方直接調用行為。例如,我們可以把用戶權限檢測封裝成一個行為類,例如:
~~~
namespace Home\Behavior;
use Think\Behavior;
class AuthCheckBehavior extends Behavior {
// 行為擴展的執行入口必須是run
public function run(&$return){
if(C('USER_AUTH_ON')) {
// 進行權限認證邏輯 如果認證通過 $return = true;
// 否則用halt輸出錯誤信息
}
}
}
~~~
定義了AuthCheck行為后,我們可以在控制器的_initialize方法中直接用下面的方式調用:
~~~
B('Home\Behavior\AuthCheck');
~~~
- 序言
- 基礎
- 獲取ThinkPHP
- 環境要求
- 目錄結構
- 入口文件
- 自動生成
- 模塊
- 控制器
- 開發規范
- 配置
- 配置格式
- 配置加載
- 讀取配置
- 動態配置
- 擴展配置
- 批量配置
- 架構
- 模塊化設計
- URL模式
- 多層MVC
- CBD模式
- 命名空間
- 自動加載
- 應用模式
- 項目編譯
- 系統流程
- 路由
- 路由定義
- 規則路由
- 正則路由
- 靜態路由
- 閉包支持
- 實例說明
- 控制器
- 控制器定義
- 前置和后置操作
- Action參數綁定
- 偽靜態
- URL大小寫
- URL生成
- AJAX返回
- 跳轉和重定向
- 輸入變量
- 請求類型
- 空操作
- 空控制器
- 插件控制器
- 操作綁定到類
- 模型
- 模型定義
- 模型實例化
- 字段定義
- 連接數據庫
- 切換數據庫
- 分布式數據庫支持
- 連貫操作
- WHERE
- TABLE
- ALIAS
- DATA
- FIELD
- ORDER
- LIMIT
- PAGE
- GROUP
- HAVING
- JOIN
- UNION
- DISTINCT
- LOCK
- CACHE
- COMMENT
- RELATION
- USING
- fetchSql
- TOKEN
- STRICT
- INDEX
- 命名范圍
- CURD操作
- 數據創建
- 數據寫入
- 數據讀取
- 數據更新
- 數據刪除
- ActiveRecord
- 字段映射
- 查詢語言
- 查詢方式
- 表達式查詢
- 快捷查詢
- 區間查詢
- 組合查詢
- 統計查詢
- SQL查詢
- 動態查詢
- 子查詢
- 自動驗證
- 自動完成
- 參數綁定
- 虛擬模型
- 模型分層
- 視圖模型
- 關聯模型
- 高級模型
- Mongo模型
- 視圖
- 模板定義
- 模板主題
- 模板賦值
- 模板渲染
- 獲取模板地址
- 獲取內容
- 模板引擎
- 模板
- 變量輸出
- 系統變量
- 使用函數
- 默認值輸出
- 使用運算符
- 標簽庫
- 模板繼承
- 修改定界符
- 三元運算
- 包含文件
- 內置標簽
- Volist標簽
- Foreach標簽
- For標簽
- Switch標簽
- 比較標簽
- 范圍判斷標簽
- IF標簽
- Present標簽
- Empty標簽
- Defined標簽
- Assign標簽
- Define標簽
- 標簽嵌套
- import標簽
- 使用PHP代碼
- 原樣輸出
- 模板注釋
- 模板布局
- 模板替換
- 調試
- 調試模式
- 異常處理
- 日志記錄
- 頁面Trace
- Trace方法
- 變量調試
- 性能調試
- 錯誤調試
- 模型調試
- 緩存
- 數據緩存
- 快速緩存
- 查詢緩存
- 靜態緩存
- 安全
- 輸入過濾
- 表單合法性檢測
- 表單令牌
- 防止SQL注入
- 目錄安全文件
- 保護模板文件
- 上傳安全
- 防止XSS攻擊
- 其他安全建議
- 擴展
- 類庫擴展
- 驅動擴展
- 緩存驅動
- 數據庫驅動
- 日志驅動
- Session驅動
- 存儲驅動
- 模板引擎驅動
- 標簽庫驅動
- 行為擴展
- 標簽擴展
- Widget擴展
- 應用模式
- 部署
- PATH_INFO支持
- URL重寫
- 模塊部署
- 域名部署
- 入口綁定
- 替換入口
- 專題
- SESSION支持
- Cookie支持
- 多語言支持
- 數據分頁
- 文件上傳
- 驗證碼
- 圖像處理
- RESTFul
- RPC
- SAE
- IP獲取和定位
- 附錄
- 常量參考
- 配置參考
- 升級指導
- 鳴謝