Laravel bootstraper 瞭解下

iffor發表於2018-07-12

LoadEnvironmentVariables,載入環境變數,預設為 .env 檔案

  • 判斷配置快取檔案是否存在,也就是`boostrap/cache/config.php是否存在,如果已經存在就不會再次去解析 .env 檔案;
  • Application 應用物件上保留了 .env 檔案的路徑和檔名稱,建立 Dotenv 物件,呼叫其 load 方法去讀取解析載入環境變數資料,Dotenv 是屬於第三方庫 vlucas/phpdotenv
  • 判斷 .env 檔案是否可讀;
  • 使用 file 函式去讀取 .env 檔案,忽略 EOL 和空白行;
  • # 開頭的為註釋行,會被過濾掉;
  • 行中含有 = 被認為是環境變數;
  • 對環境變數和值做處理,這部分可閱讀原始碼;
  • 對於已經存在的環境變數,或者系統環境變數做忽略處理;
  • 設定環境變數,具體包括 apache_setenv,putenv,$_ENV,$_SERVER

有興趣的同學可以關注下 normaliseEnvironmentVariable 方法,這裡面就包含了巢狀配置ALIAS_APP_NAME={$APP_NAME} 的實現方式。

LoadConfiguration 配置的載入

  • 判斷快取檔案 boostrap/cache/config.php 是否存在,如果存在直接 require 載入進來,然後標記 $loadedFfromCache=true
  • 建立 Repository 物件作為例項儲存在 Application 容器;
  • 如果 $loadedFromCache 不為 true 就會去載入真正的配置檔案;
  • 使用 app.env 的配置值作為 Application 的執行環境;
  • 使用 app.timezone 設定 時區;
  • 設定內部編碼為 UTF-8

通過上面的過程我們可以看出:

  • 配置資料物件 Repository 的例項以config 這個名字儲存在 Application 容器物件上;
  • 配置檔案是有快取檔案的,也就是把多個配置檔案合併起來生成一個新的快取配置檔案;
  • 時區和編碼是在配置檔案載入之後設定的;

載入配置檔案的過程如下:

  • 在建立 Application 的的時候在容器上儲存了一個名為 path.config 的變數,這個就是配置檔案的路徑;
  • 載入 path.config 下以 \*.php 結尾的檔案,然後使用 Reposiory 物件的 set 來載入設定配置資料;
  • 由於 Repository 物件已經儲存到 Application 容器物件上了,所以可以通過 config 標誌從容器裡面獲取配置資料資料,然後在獲取具體配置的值。

一般我們通過 config 函式來訪問配置檔案的資料,通過 env 函式來訪問環境變數資料。

關於查詢配置檔案的細節可以關注 symfony/finder 這個擴充套件包,基礎知識方面可以瞭解下 SPL 的 DirectoryIterator 類。

以上就是載入配置檔案的過程,並沒有看到相關生成配置快取檔案的邏輯,也就是在預設情況下是不會合並配置快取檔案的。

討論:其實預設去遍歷配置檔案目錄下的 全部 配置檔案並不是必須的,可以改為用的時候去判斷要獲取的資料是否在 Repository 物件上面,如果不存在才去載入,然後再儲存到 Repository 物件上。

HandleExceptions 異常處理設定

  • 使用 error_reporting(-1) 包括所有的錯誤;
  • set_error_handler 設定使用者自定義錯誤處理函式,具體來說就是把錯誤轉換為 ErrorException 異常物件丟擲來;
  • set_exception_handler 設定異常處理自定義函式,本質來說就是把異常交給在Application物件上註冊的Illuminate\Contracts\Debug\ExceptionHandler::class 物件去處理,首先會使用 report方法去記錄這個日誌,然後render 去把異常資訊輸出給客戶端;
  • register_shutdown_function 註冊指令碼執行完成之後的回掉,主要還是對出現了異常的處理。

至此關於錯誤與異常的系統級別的處理已經設定完畢,但在這之前出現的未被處理的異常和錯誤不會進入這裡設定的異常錯誤處理函式。

RegisterFacades Facades(門臉/別名)系統

這個系統的核心是利用spl_autoload_register註冊一個當被載入的類不存在的時候的回掉函式,它會去配置的別名列表裡面找到真正的類,然後利用class_alias 做一個別名class的別名對映,最後利用每個Facades裡面的 getFacadeAccessor 返回的實際物件在 Application 物件的標誌,最後使用Application建立出具體的物件,然後呼叫其方法。個人是比較反對這種方式的,無論是在溝通還是程式碼結構的清晰程度上都顯得複雜了不少。

RegisterProviders 註冊 ServiceProvider(服務提供者)

整個過程可以概括為,把框架,擴充套件包,專案的伺服器提供者合併為一個陣列(注意順序),然後依次建立物件,執行其 register 方法。

Service Provider 按照 $defer 的不同可以分為及時載入和延遲載入。延遲載入的實現方式在是 Application 去 make 一個物件的時候,檢查延遲服務提供者列表,如果存在就按照和普通提供者一樣的方式去註冊,建立。

BootProviders

這個引導器的主要功能是執行註冊的 Service Provider 的 boot方法,可以在這個方法裡面做一些關於 Service Provider 的初始化的操作。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章