Laravel源碼入門-啓動引導過程(一)public/index.php

開始 public/index.php

Laravel安裝完成後,啓動服務器,輸入比如 localhost:8000時,就開始啓動和引動過程。所謂請求的入口,是否可以理解爲當請求 localhost:8000時和請求 localhost:8000/login 或 localhost:8000/home 都一樣,每次的入口都是 public/index.php文件?或許是,應用的實例在初始化一次後,只要訪問有效,就不再重新實例化。

看代碼 public/index.php

<?php // public/index.php

/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <[email protected]>
 */

/*
|--------------------------------------------------------------------------
| Register The Auto Loader 註冊類自動載入
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
| 
| 實際上就是引入和執行 bootstrap/autoload.php,看看裏面的代碼,就知道了,最終引入和
| 執行了 vendor/autoload.php,而這個文件是 Composer 自動生成的。
|
*/

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

/*
|--------------------------------------------------------------------------
| Turn On The Lights 開燈點亮(創建$app實例)
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
| 開什麼燈?這個燈:bootstrap/app.php,用來照亮 La 的開發,啓動應用,更用它創造的價值
| 照亮用戶。看看 bootstrap/app.php 的代碼,可以知道,Laravel 的核心代碼庫取名爲
| Illuminate,它不僅僅是照亮的意思,是點亮,授以靈感和啓發之意。注意,這裏是
| require_once,解釋了前面的疑問,每次請求,都不是重新引入和執行。這一步創建了$app實例
|
| 這一句代碼和上一句的一個區別,特別在初學者眼中,上一句只是包含和執行了,這一句首先是
| require_once,更重要的是 bootstrap/app.php (去看看源代碼)的最後一句是
| return $app,也就是說,包含和執行後創建了 $app。
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';

/*
|--------------------------------------------------------------------------
| Run The Application 讓應用跑起來
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
| 
| 1. $app實例有了,還要做一些準備,系統才能跑起來。這裏 $app->make() 方法意味解析(resolve)
| 而不是簡單的 new 操作,之所以意味着解析(resolve),是因爲 $app 是一個容器,各種組件像藥水
| 一樣以 Injection 的方式注入到了 $app 體內,而在體外,比如 index.php 文件就相當於在 $app
| 體外,要獲得 $kernel,就可以用 $app->make(類的名字) 從各種有機融合在一起的藥水中來析出來,
| 這也就是 $app 是一個容器的 IoC 控制反轉 的理解方式。
| 具體參見https://laravel.com/docs/5.4/container,搜索 “make method”。
| 通過 make() 獲得 $kernel 實例。$kernel 的 handle() 方法,是最直接的表現:接收 $request,
| 向用戶返回 $response。注意這裏的 $kernel 來自 Illuminate\協議\Http\的Kernel,Laravel
| 還有很多 Kernel 類,見附圖。
|
| 2. 使用Illuminate\Http\Request::capture()方法來創建 $request,當然請求由客戶端發起,
| 隨後,服務器(apache或內置server)接收,生成所謂的 $request,這應該就是 capture()方法
| 的定義中所謂的“Create a new Illuminate HTTP request from server variables.”
|
| 3. 這裏有理由相信,每次客戶端請求,都會執行capture(),生成$request,內核處理後返回
| $response。接下來是 send()方法,向客戶端發回。
|
| 4. 結束請求過程,$kernel->terminate(),該方法註釋爲:
| Perform any final actions for the request lifecycle.
|
| 備註:Http表示不同與Console的,可以理解爲web端。
| 
| 備註:::class 獲取類的string值,make(Illuminate\Contracts\Http\Kernel::class)
| 相當於 make('Illuminate\Contracts\Http\Kernel::class')。
|
| 備註:這裏的 $request 和 $response 是Symfony的類實例,分別是
| \Symfony\Component\HttpFoundation\Request  $request
| \Symfony\Component\HttpFoundation\Response  $response
|
*/

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

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

$response->send();

// 這句話執行不到的
$kernel->terminate($request, $response);

 

== 總結 ==

總結:index.php做了三件事,註冊類自動載入、創建$app實例,創建$kernel,讓系統跑起來。前兩步做的需要的 bootstrap/autoload.php 和 bootstrap/app.php 都在 bootstrap 目錄中,如果把我們要基於 Laravel 開發的應用看做一隻靴子(boot)的話,那麼 autoload.php 和 app.php 就是這隻靴子(boot)的strap(鞋襻pan),鞋襻(strap)對於整隻鞋(boot)來說,輕量了很多,但關鍵時刻解決大問題,一拉一引,鞋(boot)就可以穿好(創建好$app實例),鞋好的話,真能跑起來($kernel),就這樣了。

通過這個文章,最終的目標是,初步瞭解 public/index.php 做了什麼,然後頭腦中能形成一個目錄結構圖,知道自己的理解在什麼位置,不能迷失。

==

附1:Laravel中的Kernel類,這點上Laravel顯得亂也不亂,不好評述。

附2:目錄結構圖,再有一個基本認識

 

附3:__DIR__ 是PHP魔術常量,表示文件所在的目錄。如果用在被包括文件中,則返回被包括的文件所在的目錄。它等價於dirname(__FILE__)。具體見:http://php.net/manual/zh/language.constants.predefined.php

附4:require_once 語句和 require 語句完全相同,唯一區別是 PHP 會檢查該文件是否已經被包含過,如果是則不會再次包含。include_once 語句在腳本執行期間包含並運行指定文件。此行爲和 include 語句類似,唯一區別是如果該文件中已經被包含過,則不會再次包含。如同此語句名字暗示的那樣,只會包含一次。require 和 include 幾乎完全一樣,除了處理失敗的方式不同之外。require 在出錯時產生 E_COMPILE_ERROR 級別的錯誤。換句話說將導致腳本中止而 include 只產生警告(E_WARNING),腳本會繼續運行。具體見:http://php.net/manual/zh/function.require-once.php

end

下篇 Laravel源碼入門-啓動引導過程(二)bootstrap/autoload.php

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章