## 從public目錄下的index.php入口文件開始
顯示require把base.php文件加載進來。base.php主要干了以下事情
1. 載入了系統的自動加載類(think\Loader.php)。
2. 注冊了自動加載類。
3. 注冊錯誤和異常處理機制
4. 注冊類庫別名
### 注冊錯誤和異常處理機制
類的自動加載在第一章分析過。接下來我們分析一下錯誤和異常處理。調用的是Error類的register方法。
```
Error::register();
```
由于前面已經注冊了類的自動加載,所以這里可以接著加載到think\Error的類。并調用靜態方法register
```
public static function register()?{
error_reporting(E_ALL); // 設置應該報告何種php錯誤
set_error_handler([__CLASS__,?'appError']); // 設置用戶自定義的錯誤處理函數
set_exception_handler([__CLASS__,?'appException']); // 設置用戶自定義的異常處理函數
register_shutdown_function([__CLASS__,?'appShutdown']); //它會在腳本執行完成或者exit后被調用
?}
```
> error_reporting(E_ALL); 報告所有的php錯誤。(即所有的錯誤都打印出來)
* set_error_handler設置了appError函數為自定義錯誤處理函數。看一下這個函數。
將錯誤號碼和設置的報告錯誤級別進行位運算,若匹配,則直接拋出錯誤。若不匹配,則走向框架內置的ExceptionHandler中的report方法。report方法主要是記錄日志信息。
```
public static function appError($errno,?$errstr,?$errfile?=?'',?$errline?=?0){
$exception?=?newErrorException($errno,?$errstr,?$errfile,?$errline);
if?(error_reporting()?&?$errno)?{
//?將錯誤信息托管至?think\\exception\\ErrorException
throw $exception;
????}
self::getExceptionHandler()->report($exception);
}
```
* set_exception_handler設置了appException函數為自定義的異常處理函數。看一下這個函數.
先調用report方法記錄日志。在判斷若是命令行運行,則命令行打印異常信息,若是網頁,則調用
ExceptionHandler的render方法將處理異常,最終將調用response的send方法把異常處理后的信息展示在瀏覽器端。
```
public static function appException($e)?{
// 自定義異常必須繼承\Exception類
if?(!$e?instanceof?\Exception)?{
$e?=?newThrowableError($e);
? }
self::getExceptionHandler()->report($e);
if?(PHP\_SAPI?==?'cli')?{
self::getExceptionHandler()->renderForConsole(newConsoleOutput,?$e);
?????}?else?{
self::getExceptionHandler()->render($e)->send();
?????}
?}
```
上面的self::getExceptionHandler,如果不設置的話,默認的是think\exception\Handle類。我們可以自定義一個類。但必須是需要繼承think\exception\Handle。并重寫父類的render方法。從而實現自定義異常的處理。(我們可以自定義一個類,然后再配置文件中配置exception\_handle屬性即可)
> 自定義異常處理的主要作用是根據不同的異常類型發送不同的狀態碼和響應輸出格式。需要注意的是,如果自定義異常處理類沒有再次調用系統`render`方法的話,配置`http_exception_template`就不再生效
* register_shutdown_function注冊了appShutdown函數為程序結束時調用的函數。該函數先是判斷是否是致命的錯誤導致程序結束,如果是則調用自定義錯誤處理函數。最后將信息寫入日志。
```
public static function appShutdown(){
if (!is_null($error = error_get_last()) && self::isFatal($error['type'])) {
// 將錯誤信息托管至think\ErrorException
$exception = new ErrorException($error['type'], $error['message'], $error['file'], $error['line']);
self::appException($exception);
}
// 寫入日志
Container::get('log')->save();
}
```
> error_get_last 函數返回最后一次發生錯誤的信息