摘要:異常處理上節(jié)解讀源碼一自動加載看完了自動加載部分,根據(jù)代碼執(zhí)行順序,的行注冊錯誤和異常處理機制加載慣例配置文件下面的加載配置文件不用說,現(xiàn)在重點看一下異常處理。博客鏈接解讀源碼二異常處理和請求生命周期
異常處理
上節(jié)解讀 thinkphp5 源碼(一):自動加載看完了自動加載部分,根據(jù)代碼執(zhí)行順序,base.php的59-64行
// 注冊錯誤和異常處理機制 hinkError::register(); // 加載慣例配置文件 hinkConfig::set(include THINK_PATH . "convention" . EXT);
下面的加載配置文件不用說,現(xiàn)在重點看一下異常處理。
打開library/think/Error.php,register函數(shù)。
public static function register(){ error_reporting(E_ALL); set_error_handler([__CLASS__, "appError"]); set_exception_handler([__CLASS__, "appException"]); register_shutdown_function([__CLASS__, "appShutdown"]); }
通過error_reporting()來這是php的報錯級別。E_ALL為顯示所有報錯信息,所以在運行時NOTICE級別的警告也會顯示,如果不想顯示NOTICE信息,可以在項目common文件中重新設(shè)置一下報錯級別:error_reporting(E_ALL ^ E_NOTICE);
set_error_handler指定appError來處理系統(tǒng)異常
set_exception_handler來指定appException來處理用戶拋出的異常
register_shutdown_function來指定appShutdown處理超時異常
然后使用getExceptionHandler方法來獲取異常處理對象的實例。
public static function getExceptionHandler() { static $handle; if (!$handle) { // 異常處理handle $class = Config::get("exception_handle"); if ($class && class_exists($class) && is_subclass_of($class, " hinkexceptionHandle")) { $handle = new $class; } else { $handle = new Handle; } } return $handle; }
里面有一句$class = Config::get("exception_handle");也就是說我們可以通過修改配置參數(shù)來指定新的異常處理對象。
library/think/exception/ 下是幾個異常處理類,主要就是在開啟debug的情況下輸出異常等級,異常信息,異常代碼等等。然后也對CLI模式下做了異常輸出的處理。
請求生命周期 應(yīng)用初始化base.php看完之后,基本上框架的初始化工作也做完了。然后回到,start.php中。
// 執(zhí)行應(yīng)用 App::run()->send();
這里是一個連貫操作,我們需要先看一下App::run()返回的是什么對象
library/think/App.php,run方法
run方法可以接收一個Request對象,如果不存在,則獲取該對象。
is_null($request) && $request = Request::instance();
然后通過$config = self::initCommon();來初始化應(yīng)用
看initCommon()中的代碼可以發(fā)現(xiàn)主要做了以下幾件事情。
首先通過init()方法來初始化應(yīng)用,主要就是加載該模塊或者應(yīng)用運行所需的文件,配置、common文件、語言包
然后判斷如果配置中關(guān)閉debug的話則通過ini_set("display_errors", "Off");來關(guān)閉異常信息的顯示。
ini_set("display_errors", "Off")和error_reporting(0)的區(qū)別主要在于,用前者設(shè)置后頁面不顯示異常信息,但是可以通過日志來收集異常信息,主要用在生產(chǎn)環(huán)境。而error_reporting(0);則屏蔽了所有異常信息,這種做法肯定是不太科學(xué)的。
然后判斷如果不是cli模式下則重新申請一個緩沖區(qū)。使用緩沖區(qū)的作用主要是兩方面,一是可以在輸出一些內(nèi)容之后在設(shè)置header(例如cookie等),使得程序設(shè)計的邏輯性變得簡單;二是可以對緩沖區(qū)里面的輸出內(nèi)容撤銷、刪除、壓縮、保存到文件等操作。
這里通過ob_get_level來判斷緩沖區(qū)是否為空,來處理緩沖區(qū)的歷史內(nèi)容。
然后注冊命名空間、加載額外文件、設(shè)置時區(qū)、注冊app_init的hook。
回到run方法
if (defined("BIND_MODULE")) { // 模塊/控制器綁定 BIND_MODULE && Route::bind(BIND_MODULE); } elseif ($config["auto_bind_module"]) { // 入口自動綁定 $name = pathinfo($request->baseFile(), PATHINFO_FILENAME); if ($name && "index" != $name && is_dir(APP_PATH . $name)) { Route::bind($name); } }
BIND_MODULE主要是來處理默認模塊的,tp5的路由規(guī)則是/m/c/a,如果應(yīng)用只有一個模塊,則可以用過設(shè)置BIND_MODULE常量來設(shè)置模塊名稱。
通過配置auto_bind_module參數(shù)也可以設(shè)定模塊名稱。
$request->filter($config["default_filter"]);注入過濾方法
開啟多語言支持。
路由檢測// 獲取應(yīng)用調(diào)度信息 $dispatch = self::$dispatch; if (empty($dispatch)) { // 進行URL路由檢測 $dispatch = self::routeCheck($request, $config); } // 記錄當(dāng)前調(diào)度信息 $request->dispatch($dispatch); // 記錄路由和請求信息 if (self::$debug) { Log::record("[ ROUTE ] " . var_export($dispatch, true), "info"); Log::record("[ HEADER ] " . var_export($request->header(), true), "info"); Log::record("[ PARAM ] " . var_export($request->param(), true), "info"); }
主要通過self::routeCheck($request, $config);來對路由進行分類,然后進行相應(yīng)的操作(等后面進詳細閱讀)。主要有以下幾種類別
路由到模塊/控制器/操作; 路由到外部重定向地址; 路由到控制器方法; 路由到閉包函數(shù); 路由到類的方法;路由分發(fā)
根據(jù)上面得到分類,進行相應(yīng)的操作,得到返回的數(shù)據(jù)(等后面進詳細閱讀)。
請求響應(yīng)主要通過Response類來進行響應(yīng)。
注冊app_end的hook,并返回response對象。
所以前面App::run()事實上得到的是一個經(jīng)過一系列操作之后的response對象然后執(zhí)行response->send();
拿到緩沖區(qū)中的數(shù)據(jù),并輸出,至此,結(jié)束請求。
博客鏈接:解讀 thinkphp5 源碼(二):異常處理和請求生命周期
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/30495.html
摘要:索性讀一下它的源碼。行載入類載入類,這個類比較重要,實現(xiàn)了自動加載。注冊錯誤和異常處理機制加載慣例配置文件接下來我們看一下自動加載的實現(xiàn)方法。所以借助此函數(shù)可以達到自動加載。博客鏈接解讀源碼一自動加載 聽說 TP5 已經(jīng) RC4 了,曾經(jīng)在 RC3 的時候用它寫過一個小東西。官方說從 RC4 以后改動不是太大。索性讀一下它的源碼。然后順便記錄一下,如有錯漏,請路過大神多多指正! 入口 ...
摘要:如果遍歷后沒有找到,則加載失敗。在之后碰到了之后直接拿來用,提高系統(tǒng)自動加載的性能。這里我們就講完了注冊自動加載。使用自動加載我們在中定義了我們自動加載函數(shù)式方法。 繼 生命周期的第二篇,大家盡可放心,不會隨便鴿文章的 第一篇中,我們提到了入口腳本,也說了,里面注冊了自動加載的功能 本文默認你有自動加載和命名空間的基礎(chǔ)。如果沒有請 看此篇文章 php 類的自動加載與命名空間 自動加載...
摘要:本文源碼為版本。的代碼結(jié)構(gòu)也是一個很經(jīng)典的定義結(jié)構(gòu)構(gòu)造函數(shù)實例修改函數(shù)原型共享實例方法,它提供事件通道上事件的訂閱撤消訂閱調(diào)用。 前言 cordova(PhoneGap) 是一個優(yōu)秀的經(jīng)典的中間件框架,網(wǎng)上對其源代碼解讀的文章確實不多,本系列文章試著解讀一下,以便對cordova 框架的原理理解得更深入。本文源碼為cordova android版本6.1.2。 源碼結(jié)構(gòu) 我們使用IDE...
摘要:第一篇文章我會結(jié)合和的部分源碼,來說明注入生命周期的過程。說到源碼,其實沒有想象的那么難。但是源碼的調(diào)用樹會復(fù)雜很多。應(yīng)用的業(yè)務(wù)代碼逐漸復(fù)雜,事件事件總線等通信的方式的弊端就會愈發(fā)明顯。狀態(tài)管理是組件解耦的重要手段。前言 這篇文章是【前端詞典】系列文章的第 13 篇文章,接下的 9 篇我會圍繞著 Vue 展開,希望這 9 篇文章可以使大家加深對 Vue 的了解。當(dāng)然這些文章的前提是默認你對 ...
閱讀 781·2023-04-25 16:55
閱讀 2821·2021-10-11 10:59
閱讀 2086·2021-09-09 11:38
閱讀 1800·2021-09-03 10:40
閱讀 1495·2019-08-30 15:52
閱讀 1134·2019-08-30 15:52
閱讀 965·2019-08-29 15:33
閱讀 3505·2019-08-29 11:26