請求處理
return $this->app->route->dispatch($request, $withRoute);
這里就是處理整個業務的核心,之前的事件注冊,路由注冊,中間件注冊,都會在這里執行。可能會涉及很多細節,但在這里不會細說,主要看一下整個分發的流程。看一下 dispatch 方法的代碼
public function dispatch(Request $request, $withRoute = null)
{
$this->request = $request;
// 1
$this->host = $this->request->host(true);
// 2
$this->init();
// 3
if ($withRoute) {
$checkCallback = function () use ($request, $withRoute) {
$withRoute();
return $this->check();
};
if ($this->config['route_check_cache']) {
$dispatch = $this->cache
->tag('route_cache')
->remember($this->getRouteCacheKey($request), $checkCallback);
} else {
$dispatch = $checkCallback();
}
} else {
$dispatch = $this->url($this->path());
}
// 4
$dispatch->init($this->app);
$this->app->middleware->add(function () use ($dispatch) {
try {
$response = $dispatch->run();
} catch (HttpResponseException $exception) {
$response = $exception->getResponse();
}
return $response;
});
return $this->app->middleware->dispatch($request);
}
按照 1 ~ 4 步驟進行說明
獲取域名不含端口號
初始化
route 的初始化
加載配置文件 route.php
路由是否延遲解析
設置路由緩存
如果生成了路由緩存文件就加載路由緩存文件 => runtime 目錄下的 route.php
是否開啟路由
開啟路由緩存 ,加載路由文件并且檢測 URL,設置路由緩存 key 的還會將對應路由緩存起來。
注意的是,remember 方法會執行閉包,所以存儲的并不是閉包,而是 dispatch\url 對象
獲取路由緩存的 key,這個是在配置文件設置的,還必須是設置閉包。
如果沒有開啟路由 直接解析 URL
dispatch 初始化
因為 $dispatch instanceof dispatch\Controller 所以主要初始化工作在 Controller 里面
將調度追加到中間件 middleware queue 隊列中,所以這一步最近才會執行
中間件調度執行
未啟用路由
當前所在 think\Route 類中,再往下講之前,先來看一下 url 這個方法。
public function url(string $url): UrlDispatch
{
return new UrlDispatch($this->request, $this->group, $url);
}
這段代碼很重要,因為請求在沒有啟用路由的情況是由它處理。$this->group 屬性呢就是在當前類實例化的時候設置的 think\route\Domain 域名路由類。$url 是從 pathinfo 信息中獲取的。了解了這些信息之后,直接看到步驟 4,因為上面的步驟最終目的都是獲得這個 dispatch 對象。
啟用路由的情況
啟動路由的情況會產生另外一個 Dispatch 對象 think\route\dispatch\Callback,為什么會產生兩個不同對象,具體細節在之后的路由解析中會詳細介紹,先跳過細節,看看整個過程是如何處理的。下面會分別介紹兩個對象的處理。
DisPatch 的初始化
上述兩種情況下,獲取控制和模塊的方法是完全不一樣。
前者是直接解析 URL 來獲取,就是框架以前傳統的方式 module/controller/index,然后解析出來。
后者是經過路由解析之后,才會獲取相應模塊的控制器,這部分有一定性能消耗。
所以對比來看,未啟用路由性能比較高,但是還是推薦啟用路由,這樣比較易于管理。
Dispatch 執行
因為 Dispatch run 作為閉包被加入到中間的隊列中之后,由中間件 Dispatch。關于中間執行可以參照上篇,這里需要知道的是 Dispatch 是被加到中間件隊列末尾,是在最后執行的就可以了。
主要來看 $dispatch->run(),上文說的兩個對象都是繼承 Dispatch 對象的,所以到里面看看 run 方法。
public function run(): Response
{
if ($this->rule instanceof RuleItem && $this->request->method() == 'OPTIONS' && $this->rule->isAutoOptions()) {
$rules = $this->rule->getRouter()->getRule($this->rule->getRule());
$allow = [];
foreach ($rules as $item) {
$allow[] = strtoupper($item->getMethod());
}
return Response::create('', '', 204)->header(['Allow' => implode(', ', $allow)]);
}
$option = $this->rule->getOption();
// 數據自動驗證
if (isset($option['validate'])) {
$this->autoValidate($option['validate']);
}
$data = $this->exec();
return $this->autoResponse($data);
}
啟用路由和未啟用路由完全是兩種過程,啟用理由設計到路由解析的過程,暫且擱置,后面詳細說明。下面的過程是指的未啟用路由的過程。
通過 URL 獲取訪問路徑,例如 index/index
對于這樣的 URL 默認會訪問配置文件 route.php 的 controller_layer 所設置的目錄下的類文件。框架默認設置的是 controller。創建框架的時候應該就可以看到了。
對于控制器而言可以設置控制器的中間件,對于控制器中間件作用范圍應該是執行方法之前,控制器初始化后。
設置空控制器,默認是 Error,這個似乎和以前的版本是一樣的。
這兩種方式的區別,路由訪問帶來了一定的自由目錄組織的能力,當然性能會有所損耗,Url 訪問可能限制相對而言不是那么自由,比如對于初始化框架你只能限定在 controller 目錄下創建類使用。當然這個是可以改變的,使用框架在初始化的先后循序上做一下改變,以應對框架的在 URL 解析上的規則,這個將會在下一篇事件機制上作出解答
- 空白目錄
- php語法結構
- 安裝與更新
- 開啟調試模式及代碼跟蹤器
- 架構
- 源碼分析
- 應用初始化
- 請求流程
- 中間件源碼分析
- 請求處理源碼分析
- Request源碼分析
- 模板編譯流程
- 路由與請求流程
- 容器
- 獲取目錄位置
- 入口文件
- 多應用模式及URL訪問
- 依賴注入與容器
- 容器屬性及方法
- Container
- App
- facade
- 中間件(middleware)
- 系統服務
- extend 擴展類庫
- 筆記
- 配置
- env配置定義及獲取
- 配置文件的配置獲取
- 單應用模式-(配置)文件目錄結構(默認)
- 多應用模式(配置)文件目錄結構(配置文件)
- 配置文件
- 應用配置:app.php
- 緩存配置: cache.php
- 數據庫配置:database.php
- 路由和URL配置:route.php
- Cookie配置:cookie.php
- Session配置:session.php
- 命令行配置:console.php
- 多語言配置:lang.php
- 日志配置:log.php
- 頁面Trace配置:trace.php
- 磁盤配置: filesystem.php
- 中間件配置:middleware.php
- 視圖配置:view.php
- 改成用yaconf配置
- 事件
- 例子:省略事件類的demo
- 例子2:完整事件類
- 例子3:事件訂閱,監聽多個事件
- 解析
- 路由
- 路由定義
- 路由地址
- 變量規則
- MISS路由
- URL生成
- 閉包支持
- 路由參數
- 路由中間件
- 路由分組
- 資源路由
- 注解路由
- 路由綁定
- 域名路由
- 路由緩存
- 跨域路由
- 控制器
- 控制器定義
- 空控制器、空操作
- 空模塊處理
- RESTFul資源控制器
- 控制器中間件
- 請求對象Request(url參數)
- 請求信息
- 獲取輸入變量($_POST、$_GET等)
- 請求類型的獲取與偽裝
- HTTP頭信息
- 偽靜態
- 參數綁定
- 請求緩存
- 響應對象Response
- 響應輸出
- 響應參數
- 重定向
- 文件下載
- 錯誤頁面的處理辦法
- 應用公共文件common.php
- 模型
- 模型定義及常規屬性
- 模型數據獲取與模型賦值
- 查詢
- 數據集
- 增加
- 修改
- 刪除
- 條件
- 查詢范圍scope
- 獲取器
- 修改器
- 搜索器
- 軟刪除
- 模型事件
- 關聯預載入
- 模型關聯
- 一對一關聯
- 一對多關聯
- 多對多關聯
- 自動時間戳
- 事務
- 數據庫
- 查詢構造器
- 查詢合集
- 子查詢
- 聚合查詢
- 時間查詢
- 視圖查詢(比join簡單)
- 獲取查詢參數
- 快捷方法
- 動態查詢
- 條件查詢
- 打印sql語句
- 增
- 刪
- 改
- 查
- 鏈式操作
- 查詢表達式
- 分頁查詢
- 原生查詢
- JSON字段
- 鏈接數據庫配置
- 分布式數據庫
- 查詢事件
- Db獲取器
- 事務操作
- 存儲過程
- Db數據集
- 數據庫驅動
- 視圖
- 模板
- 模板配置
- 模板位置
- 模板渲染
- 模板變量與賦值(assign)
- 模板輸出替換
- url生成
- 模板詳解
- 內置標簽
- 三元運算
- 變量輸出
- 函數輸出
- Request請求參數
- 模板注釋及原樣輸出
- 模板繼承
- 模板布局
- 原生PHP
- 模板引擎
- 視圖過濾
- 視圖驅動
- 驗證
- 驗證進階之最終版
- 錯誤和日志
- 異常處理
- 日志處理
- 調試
- 調試模式
- Trace調試
- SQL調試
- 變量調試
- 遠程調試
- 雜項
- 緩存
- Session
- Cookie
- 多語言
- 上傳
- 擴展說明
- N+1查詢
- TP類庫
- 擴展類庫
- 數據庫遷移工具
- Workerman
- think助手工具庫
- 驗證碼
- Swoole
- request
- app
- Response
- View
- Validate
- Config
- 命令行
- 助手函數
- 升級指導(功能的添加與刪除說明)
- siyucms
- 開始
- 添加頁面流程
- 列表頁加載流程
- 彈出框
- 基礎控制器
- 基礎模型
- 快速構建
- 表單form構建
- 表格table構建
- MakeBuilder
- 前端組件
- 日期組件
- layer 彈層組件
- Moment.js 日期處理插件
- siyucms模板布局
- 函數即其變量
- 前端頁面
- $.operate.方法
- $.modal.方法:彈出層
- $.common.方法:通用方法
- 被cms重寫的表格options
- 自定義模板
- 搜索框
- 自定義form表單
- 獲取表單搜索參數并組裝為url字符串