如何通過查原始碼的方式解決程式設計中遇到的問題?
點選進入“PHP開源社群”
免費獲取進階面試、文件、視訊資源
一.首先丟擲疑問:
1.laravel的底層是如何處理HTTP請求的?
2.laravel的Request是如何實現的?
3.為什麼不需要配置Nginx的url解析,也不需要在laravel的router中配置引數名稱,卻可以通過Request接收到引數呢?實現原理是什麼?
二. 下面開始進入查原始碼之旅:
1.首先調研了一下laravel的request是基於什麼實現的?
2.知識點如下:laravel的很多底層元件是基於Symfony實現的,比如:請求、響應、cookie、命令列,檔案等。其中HttpFoundation元件是http請求中比較重要的基礎元件,它可以獨立於Symfony使用的,laravel基於此做了進一步的封裝,使用示例如下
$request->input('param');
$request->cookie('cookie');
$request->file('file');
3.考慮到laravel專案所有的HTTP請求都會轉發到laravel的入口檔案(public/index.php),所以我們檢視這個檔案一探究竟:
//建立Application例項,作為服務容器
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
//以單例方式在服務容器中將 App\Http\Kernel 例項繫結到 Illuminate\Contracts\Http\Kernel 介面
$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
App\Http\Kernel::class
);
//服務容器建立處理 HTTP 請求的核心例項(Kernel)
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
//核心方法:處理 HTTP 請求的核心程式碼(核心程式碼會在下一部分展開來講,先從上而下理清流程)
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
//傳送響應給傳送請求的客戶端
$response->send();
//核心例項終止程式,基於傳入的request和response做一些收尾工作
$kernel->terminate($request, $response);
4.上面的註釋已經比較清楚的解釋了laravel處理HTTP請求的內部實現流程。
5.我們再繼續深入核心程式碼,研究一下“laravel為什麼在路由中無需指定引數是什麼,在控制器方法中傳入Request就可以獲得引數了呢?”
比如:
//路由
Route::resource('/index', 'IndexController');
//controller中的方法
function index(Request $request)
{
switch ($request->type) {
.
.
.
}
}
6.下面的非核心程式碼用豎著的3個.省略,避免誤導
//laravel專案的入口檔案 index.php
.
.
.
//重點1:handle()方法
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
.
.
.
//深入原始碼1 capture()
public static function capture()
{
static::enableHttpMethodParameterOverride();
//重點2:createFromBase() 方法
return static::createFromBase(SymfonyRequest::createFromGlobals());
}
//我們再深入原始碼2 createFromBase()
public static function createFromBase(SymfonyRequest $request)
{
if ($request instanceof static) {
return $request;
}
$content = $request->content;
//這是解決疑問的關鍵程式碼 duplicate 意為複製一份
$request = (new static)->duplicate(
$request->query->all(), $request->request->all(), $request->attributes->all(),
$request->cookies->all(), $request->files->all(), $request->server->all()
);
$request->content = $content;
$request->request = $request->getInputSource();
return $request;
}
7.發現了一個神奇的方法:duplicate(),意為複製一份。
8.duplicate()方法的引數,包括$request->query->all(), $request->request->all()…等,即底層已經實現了所有query和request的接收,我們不需要單獨宣告也是可以接收到所有請求引數的。
$request = (new static)->duplicate(
$request->query->all(), $request->request->all(), $request->attributes->all(),
$request->cookies->all(), $request->files->all(), $request->server->all()
);
9.上 面就是我查詢原始碼的流程:
a.明確自己的問題(Request的底層實現)
b明確自己排查問題的邊界(從入口檔案入手)
c.一層一層的深入查詢原始碼(原始碼1->原始碼2–>原始碼3)
d.排除非核心程式碼,找到最核心程式碼(duplicate()方法)
三.最後 還有一個小插曲:
原始碼這麼寫的原因是什麼?不是重複操作嗎?
不認真呀,仔細看一下,2中的request是通過 (new static)->duplicate()克隆的新物件,和1中的request並不是相同的例項。
*宣告:本文於網路整理,版權歸原作者所有,如來源資訊有誤或侵犯權益,請聯絡我們刪除或授權事宜。
END
PHP開源社群
掃描關注 進入”PHP資料“
免費獲取進階
面試、文件、視訊資源
點選“檢視原文”獲取更多
- 用“最好的語言”PHP,做一個機器學習資料集
- PHP開發中,如何做錯誤與異常處理呢 ?
- phper如何用Rust開發PHP擴充套件Liunx版【詳細教程】
- PHP 使用 CURL 詳解
- 小程式如何使用訂閱訊息(PHP程式碼 小程式js程式碼)
- MySQL提高效能,緩解資料庫壓力,你會做讀寫分離嗎?
- 深入理解 glibc malloc:記憶體分配器實現原理
- Laravel 成為最佳 PHP 框架的 14 個理由!
- 7 款顏值 yyds 的 Linux 作業系統 !
- 一文了解“最好程式語言”PHP 必知的 16 個程式設計法則!
- 終於有人把 "單點" 登入說清楚了!
- PHP程式執行Python指令碼(接收資料及傳參)
- 服務端 TCP 連線 TIME_WAIT 怎麼破?
- Shell 分析日誌檔案命令全面總結!
- 有些PHP程式設計師,不知道如何有效的除錯BUG
- 10個你可能不曾用過卻很有用的 Linux 命令
- PHP如何解決百萬級全站使用者訊息推送問題
- PHP Redis快取技術一覽
- Seata-php 入門與下半年展望
- 3 個PHP 知識總結:Memcache、快取和正則