`ThinkPHP`支持傳統的`MVC`(Model-View-Controller)模式以及流行的`MVVM`(Model-View-ViewModel)模式的應用開發,但無論采用何種模式,URL的規范仍然是統一的。
`5.1`的URL訪問受路由決定,如果在沒有定義或匹配路由的情況下(并且沒有開啟強制路由模式的話),則是基于:
>[info]http://serverName/index.php(或者其它入口文件)/模塊/控制器/操作/參數/值…
下面的一些概念有必要做下了解,可能在后面的內容中經常會被提及。
## 入口文件
用戶請求的PHP文件,負責處理一個請求(注意,不一定是URL請求)的生命周期,最常見的入口文件就是`index.php`,有時候也會為了某些特殊的需求而增加新的入口文件,例如給后臺模塊單獨設置的一個入口文件`admin.php`或者一個命令行程序入口`think`都屬于入口文件。
## 應用
應用在`ThinkPHP`中是一個管理系統架構及生命周期的對象,由系統的 `\think\App`類完成,應用通常在入口文件中被調用和執行,具有相同的應用目錄的應用我們認為是同一個應用,但一個應用可能存在多個入口文件(綁定不同的模塊或者使用不同的配置)。
應用具有自己獨立的配置文件、公共(函數)文件和路由定義文件。
## 路由
路由是用于規劃(一般同時也會進行簡化)請求的訪問地址,在訪問地址和實際操作方法之間建立一個路由規則 => 路由地址的映射關系。
ThinkPHP并非強制使用路由,如果沒有定義路由,則可以直接使用“模塊/控制器/操作”的方式訪問,如果定義了路由,則該路由對應的路由地址就被不能直接訪問了。一旦開啟強制路由參數,則必須為每個請求定義路由(包括首頁)。
使用路由有一定的性能損失,但隨之也更加安全,因為每個路由都有自己的生效條件,如果不滿足條件的請求是被過濾的。你遠比你在控制器的操作中進行各種判斷要實用的多。
其實路由的作用遠非URL規范這么簡單,還可以實現驗證、權限、參數綁定及響應設置等功能。
## 模塊
一個典型的應用是由多個模塊組成的,這些模塊通常都是應用目錄下面的一個子目錄,每個模塊都有自己獨立的配置文件、公共文件和類庫文件。
支持單一模塊架構設計,如果你的應用下面只有一個模塊,那么通過配置這個模塊的子目錄可以省略(同時應用類庫的命名空間也隨之簡化)。
## 控制器
每個模塊擁有獨立的類庫及配置文件,一個模塊下面有多個控制器負責響應請求,而每個控制器其實就是一個獨立的控制器類。
控制器主要負責請求的接收,并調用相關的模型處理,并最終通過視圖輸出。嚴格來說,控制器不應該過多的介入業務邏輯處理。
>[danger] 事實上,控制器是可以被跳過的,通過路由我們可以直接把請求調度到某個模型或者其他的類進行處理。
`ThinkPHP`的控制器類比較靈活,可以無需繼承任何基礎類庫。
一個典型的`Index`控制器類如下:
~~~
namespace app\index\controller;
class Index
{
public function index()
{
return 'hello,thinkphp!';
}
}
~~~
> 繼承系統控制器`think\Controller`的話,可以使用內置的功能,享受更多的便利。
## 操作
一個控制器包含多個操作(方法),操作方法是一個URL訪問的最小單元。
下面是一個典型的`Index`控制器的操作方法定義,包含了兩個操作方法:
~~~
namespace app\index\controller;
class Index
{
public function index()
{
return 'index';
}
public function hello($name)
{
return 'Hello,'.$name;
}
}
~~~
操作方法可以不使用任何參數,如果定義了一個非可選參數,則該參數必須通過用戶請求傳入,如果是URL請求,則通常是通過當前的請求傳入。
## 模型
模型類通常完成實際的業務邏輯和數據封裝,并返回和格式無關的數據。
>[danger] 模型類并不一定要訪問數據庫,而且在5.1的架構設計中,只有進行實際的數據庫查詢操作的時候,才會進行數據庫的連接,是真正的惰性連接。
ThinkPHP的模型層支持多層設計,你可以對模型層進行更細化的設計和分工,例如把模型層分為邏輯層/服務層/事件層等等。
## 視圖
控制器調用模型類后,返回的數據通過視圖組裝成不同格式的輸出。視圖根據不同的需求,來決定調用模板引擎進行內容解析后輸出還是直接輸出。
視圖通常會有一系列的模板文件對應不同的控制器和操作方法,并且支持動態設置模板目錄。
## 模板引擎
模板文件中可以使用一些特殊的模板標簽,這些標簽的解析通常由模板引擎負責實現。
ThinkPHP內置了一個基于XML解析的編譯型模板引擎,可以很方便的實現模板輸出和控制。
同時也可以支持第三方的模板引擎擴展。
## 驅動
系統很多的組件都采用驅動式設計,從而可以更靈活的擴展,驅動類的位置默認是放入核心類庫目錄下面,也可以重新定義驅動類庫的命名空間而改變驅動的文件位置。
>[danger] 5.1版本的驅動更多是采用`Composer`的方式安裝和管理。
## 行為
行為(`Behavior`)是在預先定義好的一個應用鉤子(`Hook`)位置執行的一些操作。類似于`AOP`編程中的“切面”的概念,給某一個鉤子綁定相關行為就成了一種類`AOP`編程的思想。
所以,行為通常是和某個`Hook`位置相關,行為的執行時間取決于行為綁定到了哪個位置上。
要執行行為,首先要在應用程序中進行行為偵聽,例如:
~~~
// 在app_init位置偵聽行為
\think\facade\Hook::listen('app_init');
~~~
然后對某個位置進行行為綁定:
~~~
// 綁定行為到app_init位置
\think\facade\Hook::add('app_init','\app\index\behavior\Test');
~~~
一個位置上如果綁定了多個行為的,按照綁定的順序依次執行,除非遇到中斷。
## 中間件
中間件主要用于HTTP請求的攔截處理
## 事件
ThinkPHP5中的事件一般是指數據庫操作和模型操作在完成數據寫入之后的回調機制。
數據庫操作的回調也稱為查詢事件,是針對數據庫的CURD操作而設計的回調方法,主要包括:
| 事件 | 描述 |
| --- | --- |
| before_select | `select`查詢前回調 |
| before_find | `find`查詢前回調 |
| after_insert | `insert`操作成功后回調 |
| after_update | `update`操作成功后回調 |
| after_delete | `delete`操作成功后回調 |
模型事件可以看成是模型層的鉤子和行為,只不過鉤子的位置主要針對模型數據的寫入操作,包含下面這些:
| 鉤子 | 對應操作 | 快捷注冊方法 |
| --- | --- | --- |
| before_insert | 新增前 | beforeInsert |
| after_insert | 新增后 | afterInsert |
| before_update | 更新前 | beforeUpdate |
| after_update | 更新后 | afterUpdate |
| before_write | 寫入前 | beforeWrite |
| after_write | 寫入后 | afterWrite |
| before_delete | 刪除前 | beforeDelete |
| after_delete | 刪除后 | afterDelete |
`before_write`和`after_write`表示無論是新增還是更新都會執行的鉤子。
## 助手函數
系統為一些常用的操作提供了助手函數支持,但核心框架本身并不依賴任何助手函數。使用助手函數和性能并無直接影響,只是某些時候無法享受IDE自動提醒的便利,但是否使用助手函數看項目自身規范,在應用的公共函數文件中也可以對系統提供的助手函數進行重寫。
- 序言
- 基礎
- 安裝
- 開發規范
- 目錄結構
- 配置
- 架構
- 架構總覽
- 入口文件
- URL訪問
- 模塊設計
- 命名空間
- 容器和依賴注入
- Facade
- 鉤子和行為
- 中間件
- 路由
- 路由定義
- 變量規則
- 路由地址
- 閉包支持
- 路由參數
- 路由緩存
- 跨域請求
- 注解路由
- 路由分組
- MISS路由
- 資源路由
- 快捷路由
- 路由別名
- 路由綁定
- 域名路由
- URL生成
- 控制器
- 控制器定義
- 前置操作
- 跳轉和重定向
- 空操作和空控制器
- 分層控制器
- 資源控制器
- 控制器中間件
- 請求
- 請求對象
- 請求信息
- 輸入變量
- 請求類型
- HTTP頭信息
- 偽靜態
- 參數綁定
- 請求緩存
- 響應
- 響應輸出
- 響應參數
- 重定向
- 文件下載
- 數據庫
- 連接數據庫
- 查詢構造器
- 查詢數據
- 添加數據
- 更新數據
- 刪除數據
- 查詢表達式
- 鏈式操作
- where
- table
- alias
- field
- strict
- limit
- page
- order
- group
- having
- join
- union
- distinct
- lock
- cache
- comment
- fetchSql
- force
- partition
- failException
- sequence
- 聚合查詢
- 時間查詢
- 高級查詢
- 視圖查詢
- JSON字段
- 子查詢
- 原生查詢
- 查詢事件
- 獲取器
- 事務操作
- 監聽SQL
- 存儲過程
- 數據集
- 分布式數據庫
- 模型
- 定義
- 新增
- 更新
- 刪除
- 查詢
- JSON字段
- 獲取器
- 修改器
- 搜索器
- 數據集
- 自動時間戳
- 只讀字段
- 軟刪除
- 類型轉換
- 數據完成
- 查詢范圍
- 模型輸出
- 模型事件
- 模型關聯
- 一對一關聯
- 一對多關聯
- 遠程一對多
- 多對多關聯
- 多態關聯
- 關聯預載入
- 關聯統計
- 關聯輸出
- 視圖
- 視圖渲染
- 視圖賦值
- 視圖過濾
- 模板引擎
- 模板
- 變量輸出
- 使用函數
- 運算符
- 原樣輸出
- 模板注釋
- 模板布局
- 模板繼承
- 包含文件
- 輸出替換
- 標簽庫
- 內置標簽
- 循環標簽
- 比較標簽
- 條件判斷
- 資源文件加載
- 標簽嵌套
- 原生PHP
- 定義標簽
- 標簽擴展
- 錯誤和日志
- 異常處理
- 日志處理
- 調試
- 調試模式
- Trace調試
- 性能調試
- SQL調試
- 變量調試
- 遠程調試
- 驗證
- 驗證器
- 驗證規則
- 錯誤信息
- 驗證場景
- 路由驗證
- 內置規則
- 獨立驗證
- 靜態調用
- 表單令牌
- 雜項
- 緩存
- Session
- Cookie
- 多語言
- 分頁
- 上傳
- 命令行
- 啟動內置服務器
- 查看版本
- 自動生成目錄結構
- 創建類庫文件
- 生成類庫映射文件
- 清除緩存文件
- 生成配置緩存文件
- 生成數據表字段緩存
- 生成路由映射緩存
- 輸出路由定義
- 自定義指令
- 擴展庫
- 驗證碼
- 圖像處理
- Time
- 數據庫遷移工具
- Swoole
- Workerman
- MongoDb
- 單元測試
- 安全和性能
- 安全建議
- 優化建議
- 附錄
- 助手函數
- 升級指導
- 更新日志