項目目錄相對為tp6
請求被統一轉發到入口文件(入口文件地址為?tp6/index.php)
1.入口文件引入了composer自動載入文件類庫
```
`<php?`
`namespace``think;`
`require``__DIR__ .``'/../vendor/autoload.php'``;`
```
(文件地址為?tp6/vendor/autoload.php')
2.實例化?think\\App?對象?賦值給$app
```
`<?php`
`$app``=``new``App();`
```
(App類文件地址為?tp6/vendor/topthink/framework/src/think/App.php')
執行App類中的\_\_construct構造方法
```
`<?php`
`public``function``__construct(string``$rootPath``=``''``)`
`{`
`// 框架類庫目錄`
`$this``->thinkPath?? = dirname(__DIR__) . DIRECTORY_SEPARATOR;`
`// 項目根目錄`
`$this``->rootPath??? =``$rootPath``? rtrim(``$rootPath``, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR :``$this``->getDefaultRootPath();`
`// 應用目錄`
`$this``->appPath???? =``$this``->rootPath .``'app'``. DIRECTORY_SEPARATOR;`
`// 項目緩存目錄`
`$this``->runtimePath =``$this``->rootPath .``'runtime'``. DIRECTORY_SEPARATOR;`
`// 加載服務provide容器`
`if``(``is_file``(``$this``->appPath .``'provider.php'``)) {`
`// 執行 Container\bind()方法 綁定類、閉包、實例、接口`
`$this``->bind(``include``$this``->appPath .``'provider.php'``);`
`}`
`// 設置一個容器實例`
`static``::setInstance(``$this``);`
`// 綁定類的實例到容器`
`$this``->instance(``'app'``,``$this``);`
`$this``->instance(``'think\Container'``,``$this``);`
`}`
```
其中在屬性$bind中已經有了一些框架類的別名與實現的映射數組
此時$app因為是繼承了Container類,所以$app實際也是一個容器
3.通過$app類調用http類(web管理類)
```
`$http``=``$app``->http;`
```
3.0?引用http類的過程如下:
(http類文件地址為?tp6/vendor/topthink/framework/src/think/Http.php')
3.1?首先App中不存在http方法,但是在容器類中存在魔術方法\_\_get,會觸發該魔術方法
```
`<?php`
`public``function``__get(``$name``)`
`{`
`return``$this``->get(``$name``);`
`}`
```
get方法從app應用容器中獲取http對象實例
```
`<php?`
`/**`
`* 獲取容器中的對象實例`
`* @access public`
`* @param string $abstract 類名或者標識`
`* @return object`
`*/`
`public``function``get(``$abstract``)`
`{`
`if``(``$this``->has(``$abstract``)) {`
`return``$this``->make(``$abstract``);`
`}`
`throw``new``ClassNotFoundException(``'class not exists: '``.``$abstract``,``$abstract``);`
`}`
```
3.2?通過app應用容器中的make方法進行類的實例,以及執行instances方法將實例化的http類綁定到容器數組對象中
```
`<?php`
`/**`
`* 創建類的實例 已經存在則直接獲取`
`* @access public`
`* @param string $abstract??? 類名或者標識`
`* @param array? $vars??????? 變量`
`* @param bool?? $newInstance 是否每次創建新的實例`
`* @return mixed`
`*/`
`public``function``make(string``$abstract``,``array``$vars``= [], bool``$newInstance``= false)`
`{`
`$abstract``=``$this``->getAlias(``$abstract``);`
`if``(isset(``$this``->instances[``$abstract``]) && !``$newInstance``) {`
`return``$this``->instances[``$abstract``];`
`}`
`if``(isset(``$this``->bind[``$abstract``]) &&``$this``->bind[``$abstract``]``instanceof``Closure) {`
`$object``=``$this``->invokeFunction(``$this``->bind[``$abstract``],``$vars``);`
`}``else``{`
`$object``=``$this``->invokeClass(``$abstract``,``$vars``);`
`}`
`if``(!``$newInstance``) {`
`$this``->instances[``$abstract``] =``$object``;`
`}`
`return``$object``;`
`}`
```
返回http對象實例到調用處?第3步開始的地方
4?http對象執行run方法,應用程序的執行開始
```
`<?php`
`/**`
`* 執行應用程序`
`* @access public`
`* @param Request|null $request`
`* @return Response`
`*/`
`public``function``run(Request``$request``= null): Response`
`{`
`//自動創建request對象`
`$request``=``$request``??``$this``->app->make(``'request'``, [], true);`
`// 綁定request類的實例化對象到容器中`
`$this``->app->instance(``'request'``,``$request``);`
`try``{`
`// 執行應用程序返回response類`
`$response``=``$this``->runWithRequest(``$request``);`
`}``catch``(Throwable``$e``) {`
`$this``->reportException(``$e``);`
`$response``=``$this``->renderException(``$request``,``$e``);`
`}`
`return``$response``;`
`}`
```
4.1?run?方法中首先創建Request類,執行instances方法將實例化的Request類綁定到容器數組對象中,標識為request
然后進行路由調度,執行?app容器中runWithRequest方法
```
`/**`
`* 執行應用程序`
`* @param Request $request`
`* @return mixed`
`*/`
`protected``function``runWithRequest(Request``$request``)`
`{`
`// 初始化app應用程序`
`$this``->initialize();`
`// 加載全局中間件`
`$this``->loadMiddleware();`
`// 監聽HttpRun`
`$this``->app->event->trigger(HttpRun::``class``);`
`// 中間件調度`
`return``$this``->app->middleware->pipeline()`
`->send(``$request``)`
`->then(``function``(``$request``) {`
`return``$this``->dispatchToRoute(``$request``);`
`});`
`}`
```
4.2然后在在http類中runWithRequest方法中執行了dispatchToRoute?講請求分發到路由
?(dispatchToRoute?類方法的文件地址為?tp6/vendor/topthink/framework/src/think/Route.php')
//?分發請求到路由
```
`<?php`
`protected``function``dispatchToRoute(``$request``)`
`{`
`// 是否啟用路由, 默認啟用路由`
`$withRoute``=``$this``->app->config->get(``'app.with_route'``, true) ?``function``() {`
`$this``->loadRoutes();`
`} : null;`
`// 執行路由調度`
`return``$this``->app->route->dispatch(``$request``,``$withRoute``);`
`}`
```
4.3?在http類中dispatchToRoute?通過app容器獲取了route實例,并調用了route實例中的dispatch方法
```
<?php
/\*\*
\*?路由調度
\*?@param?Request?$request
\*?@param?Closure|bool?$withRoute
\*?@return?Response
\*/
public?function?dispatch(Request?$request,?$withRoute?=?true)
{
????$this->request?=?$request;
????$this->host????=?$this->request->host(true);
????$this->init();
????if?($withRoute)?{
????????//?加載路由設置
????????if?($withRoute?instanceof?Closure)?{
????????????$withRoute();
????????}
????????//?檢查路由
????????$dispatch?=?$this->check();
????}?else?{
????????//?如果沒有路由,則使用默認url解析
????????$dispatch?=?$this->url($this->path());
????}
????//?$dispatch?為think\\route\\dispatch\\Controller?的實例化?中的初始化,提取控制名稱以及操作名稱
????//?1,?通過最終think\\route\\Rule::dispatch來確路由調度的最終執行動作
????$dispatch->init($this->app);
????return?$this->app->middleware->pipeline('route')
????????->send($request)
????????->then(function?()?use?($dispatch)?{
????????????//?執行動作方法
????????????return?$dispatch->run();
????????});
}
```
4.4?在route類中的dispatch中執行了run方法,?
(run?類方法的文件地址為?tp6/vendor/topthink/framework/src/think/route/Dispatch.php')
```
`<?php<br>``/**`
`* 執行路由調度`
`* @access public`
`* @return mixed`
`*/`
`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(``''``,``'html'``, 204)->header([``'Allow'``=> implode(``', '``,``$allow``)]);`
`}`
`// 此處調用的$this類,由調用者確定, 可能為url, callback, 或者controller`
`// $data 為返回的response 類`
`$data``=``$this``->``exec``();`
`return``$this``->autoResponse(``$data``);`
`}`
```
4.5?run方法調用了exec?
(此處調用的exec的類方法所在的文件,由調用者確定,?可能為url,?callback,?或者controller,?exec?類方法的文件地址為?tp6/vendor/topthink/framework/src/think/route/dispatch/Callback.php|Controller.php')
在exec方法中最終返回了data數據
4.6?然后調用了autoResponse方法,并傳遞4.5返回的data數據
(autoResponse?類方法的文件地址為?tp6/vendor/topthink/framework/src/think/route/Dispatch.php')
```
`<?php`
`protected``function``autoResponse(``$data``): Response`
`{`
`if``(``$data``instanceof``Response) {`
`$response``=``$data``;`
`}``elseif``(!``is_null``(``$data``)) {`
`// 默認自動識別響應輸出類型`
`$type`????`=``$this``->request->isJson() ?``'json'``:``'html'``;`
`$response``= Response::create(``$data``,``$type``);`
`}``else``{`
`$data``= ob_get_clean();`
`$content`?`= false ===``$data``?``''``:``$data``;`
`$status`??`=``''``===``$content``&&``$this``->request->isJson() ? 204 : 200;`
`// 創建response類返回,使用html`
`$response``= Response::create(``$content``,``'html'``,``$status``);`
`}`
`return``$response``;`
`}`
```
4.7?autoResponse?方法中執行了?Response::create方法
最終方法返回了response對象;
(Response::create?類方法的文件地址為?tp6/vendor/topthink/framework/src/think/Response.php')
```
`<?php`
`/**`
`* 創建Response對象`
`* @access public`
`* @param? mixed? $data 輸出數據`
`* @param? string $type 輸出類型`
`* @param? int??? $code 狀態碼`
`* @return Response`
`*/`
`public``static``function``create(``$data``=``''``, string``$type``=``'html'``, int``$code``= 200): Response`
`{`
`$class``= false !==``strpos``(``$type``,``'\\'``) ?``$type``:``'\\think\\response\\'``. ucfirst(``strtolower``(``$type``));`
`return``Container::getInstance()->invokeClass(``$class``, [``$data``,``$code``]);`
`}`
```
4.8?最終返回了?response?Html類的對象實例
5?執行run方法
```
`$response``=``$http``->run();`
```
6?response?執行send輸出數據的操作;
(Html?類文件所在地址為?tp6/vendor/topthink/framework/src/think/response/Html.php?)
6.1?執行send方法
(send方法?類文件所在地址為?tp6/vendor/topthink/framework/src/think/Response.php?)
$response->send();
```
`<?php`
`/**`
`* 發送數據到客戶端`
`* @access public`
`* @return void`
`* @throws \InvalidArgumentException`
`*/`
`public``function``send(): void`
`{`
`// 處理輸出數據`
`$data``=``$this``->getContent();`
`if``(!headers_sent() && !``empty``(``$this``->header)) {`
`// 發送狀態碼`
`http_response_code(``$this``->code);`
`// 發送頭部信息`
`foreach``(``$this``->header``as``$name``=>``$val``) {`
`header(``$name``. (!``is_null``(``$val``) ?``':'``.``$val``:``''``));`
`}`
`}`
`if``(``$this``->cookie) {`
`$this``->cookie->save();`
`}`
`$this``->sendData(``$data``);`
`if``(function_exists(``'fastcgi_finish_request'``)) {`
`// 提高頁面響應`
`fastcgi_finish_request();`
`}`
`}`
```
6.1?在send方法中最終執行了?sendData?方法
(sendData方法?類文件所在地址為?tp6/vendor/topthink/framework/src/think/Response.php?)
```
`<?php`
`/**`
`* 輸出數據`
`* @access protected`
`* @param string $data 要處理的數據`
`* @return void`
`*/`
`protected``function``sendData(string``$data``): void`
`{`
`echo``$data``;`
`}`
```
7?執行?http對象中的end方法
```
`<?php`
`$http``->``end``(``$response``);`
```
(http類文件地址為?tp6/vendor/topthink/framework/src/think/Http.php')
```
`<?php`
`/**`
`* HttpEnd`
`* @param Response $response`
`* @return void`
`*/`
`public``function``end``(Response``$response``): void`
`{`
`$this``->app->event->trigger(HttpEnd::``class``,``$response``);`
`//執行中間件`
`$this``->app->middleware->``end``(``$response``);`
`// 寫入日志`
`$this``->app->log->save();`
`}`
```
8整個程序結束
應用類App繼承了Container容器類,?所有類的實例通過容器類進行統一管理,容器類為單例模式全局唯一;

- thinkphp6執行流程(一)
- php中use關鍵字用法詳解
- Thinkphp6使用騰訊云發送短信步驟
- 路由配置
- Thinkphp6,static靜態資源訪問路徑問題
- ThinkPHP6.0+ 使用Redis 原始用法
- smarty在thinkphp6.0中的最佳實踐
- Thinkphp6.0 搜索器使用方法
- 從已有安裝包(vendor)恢復 composer.json
- tp6with的用法,表間關聯查詢
- thinkphp6.x多對多如何添加中間表限制條件
- thinkphp6 安裝JWT
- 緩存類型
- 請求信息和HTTP頭信息
- 模型事件用法
- 助手函數匯總
- tp6集成Alipay 手機和電腦端支付的方法
- thinkphp6使用jwt
- 6.0session cookie cache
- tp6筆記
- TP6(thinkphp6)隊列與延時隊列
- thinkphp6 command(自定義指令)
- command(自定義指令)
- 本地文件上傳
- 緩存
- 響應
- 公共函數配置
- 七牛云+文件上傳
- thinkphp6:訪問多個redis數據源(thinkphp6.0.5 / php 7.4.9)
- 富文本編輯器wangEditor3
- IP黑名單
- 增刪改查 +文件上傳
- workerman 定時器操作控制器的方法
- 上傳文件到阿里云oss
- 短信或者郵箱驗證碼防刷代碼
- thinkphp6:訪問redis6(thinkphp 6.0.9/php 8.0.14)
- 實現關聯多個id以逗號分開查詢數據
- thinkphp6實現郵箱注冊功能的細節和代碼(點擊鏈接激活方式)
- 用mpdf生成pdf文件(php 8.1.1 / thinkphp v6.0.10LTS )
- 生成帶logo的二維碼(php 8.1.1 / thinkphp v6.0.10LTS )
- mysql數據庫使用事務(php 8.1.1 / thinkphp v6.0.10LTS)
- 一,創建過濾IP的中間件
- 源碼解析請求流程
- 驗證碼生成
- 權限管理
- 自定義異常類
- 事件監聽event-listene
- 安裝與使用think-addons
- 事件與多應用
- Workerman 基本使用
- 查詢用戶列表按拼音字母排序
- 擴展包合集
- 查詢用戶數據,但是可以通過輸入用戶昵稱來搜索用戶同時還要統計用戶的文章和粉絲數
- 根據圖片的minetype類型獲取文件真實拓展名思路
- 到處excel
- 用imagemagick庫生成縮略圖
- 生成zip壓縮包并下載
- API 多版本控制
- 用redis+lua做限流(php 8.1.1 / thinkphp v6.0.10LTS )
- 【thinkphp6源碼分析三】 APP類之父, 容器Container類
- thinkphp6表單重復提交解決辦法
- 小程序授權
- 最簡單的thinkphp6導出Excel
- 根據訪問設備不同訪問不同模塊
- 服務系統
- 前置/后置中間件
- 給接口api做簽名驗證(php 8.1.1 / thinkphp v6.0.10LTS )
- 6實現郵箱注冊功能的細節和代碼(點擊鏈接激活方式)
- 使用前后端分離的驗證碼(thinkphp 6.0.9/php 8.0.14/vue 3.2.26)
- 前后端分離:用jwt+middleware做用戶登錄驗證(php 8.1.1 / thinkphp v6.0.10LTS )
- vue前后端分離多圖上傳
- thinkphp 分組、頁面跳轉與ajax
- thinkphp6 常用方法文檔
- 手冊里沒有的一些用法
- Swagger 3 API 注釋
- PHP 秒級定時任務
- thinkphp6集成gatewayWorker(workerman)實現實時監聽
- thinkphp6按月新增數據表
- 使用redis 實現消息隊列
- api接口 統一結果返回處理類
- 使用swoole+thinkphp6.0+redis 結合開發的登錄模塊
- 給接口api做簽名驗證
- ThinkPHP6.0 + UniApp 實現小程序的 微信登錄
- ThinkPHP6.0 + Vue + ElementUI + axios 的環境安裝到實現 CURD 操作!
- 異常$e
- 參數請求驗證自定義和異常錯誤自定義