Laravel 的生命周期

世間萬物皆有生命周期,當我們使用任何工具時都需要理解它的工作原理,那么用起來就會得心應手,應用開發也是如此。理解了它的原理,那么使用起來就會游刃有余。
在了解 Laravel 的生命周期前,我們先回顧一下PHP 的生命周期。

PHP 的生命周期

PHP 的運行模式

PHP兩種運行模式是WEB模式、CLI模式。

  1. 當我們在終端敲入php這個命令的時候,使用的是CLI模式。
  2. 當使用Nginx或者別web服務器作為宿主處理一個到來的請求時,使用的是WEB模式。

生命周期

當我們請求一個php文件時,PHP 為了完成這次請求,會發生5個階段的生命周期切換:

  1. 模塊初始化(MINIT),即調用 php.ini 中指明的擴展的初始化函數進行初始化工作,如 mysql 擴展。

  2. 請求初始化(RINIT),即初始化為執行本次腳本所需要的變量名稱和變量值內容的符號表,如 $_SESSION變量。

  3. 執行該PHP腳本。

  4. 請求處理完成(Request Shutdown),按順序調用各個模塊的 RSHUTDOWN 方法,對每個變量調用 unset函數,如 unset $_SESSION 變量。

  5. 關閉模塊(Module Shutdown) , PHP調用每個擴展的 MSHUTDOWN 方法,這是各個模塊最后一次釋放內存的機會。這意味著沒有下一個請求了。

WEB模式和CLI(命令行)模式很相似,區別是:

  1. CLI 模式會在每次腳本執行經歷完整的5個周期,因為你腳本執行完不會有下一個請求;
  2. WEB模式為了應對并發,可能采用多線程,因此生命周期15有可能只執行一次,下次請求到來時重復2-4的生命周期,這樣就節省了系統模塊初始化所帶來的開銷。

可以看出PHP生命周期是很對稱的。說了這么多,就是為了定位Laravel運行在哪里,沒錯,Laravel僅僅運行再 第三個階段:

PHP生命周期

作用

理解這些,你就可以優化你的 Laravel 代碼,可以更加深入的了解 Laravel 的singleton(單例)。至少你知道了,每一次請求結束,PHP 的變量都會 unset,Laravel 的 singleton 只是在某一次請求過程中的singleton;你在 Laravel 中的靜態變量也不能在多個請求之間共享,因為每一次請求結束都會 unset。理解這些概念,是寫高質量代碼的第一步,也是最關鍵的一步。因此記住,PHP是一種腳本語言,所有的變量只會在這一次請求中生效,下次請求之時已被重置,而不像Java靜態變量擁有全局作用。

Laravel 的生命周期

概述

Laravel 的生命周期從public\index.php開始,從public\index.php結束。

請求過程

下面是 public\index.php的全部源碼,更具體來說可以分為四步:

1. require __DIR__.'/../bootstrap/autoload.php';

2. $app = require_once __DIR__.'/../bootstrap/app.php';
   $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

3. $response = $kernel->handle(
      $request = Illuminate\Http\Request::capture()
   );
   $response->send();

4. $kernel->terminate($request, $response);

以下是四步詳細的解釋是:
composer自動加載需要的類

  1. 文件載入composer生成的自動加載設置,包括所有你 composer require的依賴。

  2. 生成容器Container,Application實例,并向容器注冊核心組件(HttpKernel,ConsoleKernel ,ExceptionHandler)(對應代碼2,容器很重要,后面詳細講解)。

  3. 處理請求,生成并發送響應(對應代碼3,毫不夸張的說,你99%的代碼都運行在這個小小的handle 方法里面)。

  4. 請求結束,進行回調(對應代碼4,還記得可終止中間件嗎?沒錯,就是在這里回調的)。

Laravel 的請求步驟

我們不妨在詳細一點:

第一步:注冊加載composer自動生成的class loader

就是加載初始化第三方依賴。

第二步:生成容器 Container

并向容器注冊核心組件,是從 bootstrap/app.php 腳本獲取 Laravel 應用實例,

第三步:這一步是重點,處理請求,并生成發送響應。

請求被發送到 HTTP 內核或 Console 內核,這取決于進入應用的請求類型。

取決于是通過瀏覽器請求還是通過控制臺請求。這里我們主要是通過瀏覽器請求。

HTTP 內核的標志性方法 handle處理的邏輯相當簡單:獲取一個 Request,返回一個 Response,把該內核想象作一個代表整個應用的大黑盒子,輸入 HTTP 請求,返回 HTTP 響應。

1. 首先 Bootstrap 檢測環境,加載 bootstrapper數組中的一些配置

HTTP 內核繼承自 Illuminate\Foundation\Http\Kernel 類,該類定義了一個 bootstrappers 數組,這個數組中的類在請求被執行前運行,這些 bootstrappers 配置了錯誤處理、日志、檢測應用環境以及其它在請求被處理前需要執行的任務。

protected $bootstrappers = [
        //注冊系統環境配置 (.env)
        'Illuminate\Foundation\Bootstrap\DetectEnvironment',
        //注冊系統配置(config)
        'Illuminate\Foundation\Bootstrap\LoadConfiguration',
        //注冊日志配置
        'Illuminate\Foundation\Bootstrap\ConfigureLogging',
        //注冊異常處理
        'Illuminate\Foundation\Bootstrap\HandleExceptions',
        //注冊服務容器的門面,Facade 是個提供從容器訪問對象的類。
        'Illuminate\Foundation\Bootstrap\RegisterFacades',
        //注冊服務提供者
        'Illuminate\Foundation\Bootstrap\RegisterProviders',
        //注冊服務提供者 `boot`
        'Illuminate\Foundation\Bootstrap\BootProviders',
    ];

注意順序:
Facades 先于ServiceProvidersFacades也是重點,后面說,這里簡單提一下,注冊 Facades 就是注冊 config\app.php中的aliases 數組,你使用的很多類,如AuthCache,DB等等都是Facades;而ServiceProvidersregister方法永遠先于boot方法執行,以免產生boot方法依賴某個實例而該實例還未注冊的現象。

HTTP 內核還定義了一系列所有請求在處理前需要經過的 HTTP 中間件,這些中間件處理 HTTP 會話的讀寫、判斷應用是否處于維護模式、驗證 CSRF 令牌等等。

2. 第一堵墻,全局中間件,默認為 CheckForMaintenanceMode

在Laravel基礎的服務啟動之后,就要把請求傳遞給路由了。路由器將會分發請求到路由或控制器,同時運行所有路由指定的中間件。

傳遞方式

傳遞給路由是通過 Pipeline(管道)來傳遞的,但是Pipeline有一堵墻,在傳遞給路由之前所有請求都要經過,這堵墻定義在app\Http\Kernel.php中的$middleware數組中,沒錯就是中間件,默認只有一個CheckForMaintenanceMode中間件,用來檢測你的網站是否暫時關閉。這是一個全局中間件,所有請求都要經過,你也可以添加自己的全局中間件。

3. 然后遍歷所有注冊的路由,找到最先符合的第一個路由

然后遍歷所有注冊的路由,找到最先符合的第一個路由,

4. 第二堵墻,通過該路由的中間件(組)

經過該路由中間件,進入到控制器或者閉包函數,執行你的具體邏輯代碼。

所以,當請求到達你寫的代碼之前,Laravel已經做了大量工作,請求也經過了千難萬險,那些不符合或者惡意的的請求已被Laravel隔離在外。

處理請求到響應過程
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • 原文鏈接 必備品 文檔:Documentation API:API Reference 視頻:Laracasts ...
    layjoy閱讀 8,619評論 0 121
  • laravel生命周期從全部包含在public\index.php文件中
    fireinme閱讀 1,041評論 0 1
  • 0.1配置1.模板繼承2.控制器3.git4.支付寶支付的流程5.路由6.中間件7.請求8.laravel 學習筆...
    云龍789閱讀 816評論 0 5
  • 真正的愛是,明知他/她愛的不是自己,卻仍可以為了他/她,傾盡自己的所有,甚至是性命也在所不惜。 ...
    愿逐月華留照君閱讀 956評論 0 2