之前講到過對於異常的處理機制,最好可以自訂異常,如果debug開啟,那麼顯示具體的調試資訊,如果debug關閉,那麼將異常記錄到日誌,然後跳轉到錯誤頁,這節課我就主要來講一下這個異常處理機制。
現在我們定義一個異常的基類,在Toper中為Tp_Exception,在這兒,我就直接叫BaseException吧,那BaseException.php肯定首先是有一個架子的:
| 2 |
class BaseException extends Exception { |
| 3 |
public function printStack() { |
| 6 |
public function __toString() { |
最基礎的,這個類肯定要繼承自Exception,然後我需要實現__toString方法和另外一個自訂的printStack方法,實現__toString方法的原因是經常我們會直接throw new Exception() 這種方式拋出異常,它會直接調用__toString()方法,調用printStack方法就是輸出堆棧資訊。
說一下思路,首先這兩個方法我們都需要判定是否是debug模式,如果是debug模式,那麼很easy,直接輸出即可,否則,跳轉到錯誤頁,但是跳轉之前,必須要將異常資訊寫入到記錄檔中去。
可能大家注意到,不管是__toString還是printStack如果debug關閉,都需要記錄調試資訊到記錄檔,所以我們需要首先編寫一個輔助函數:
| 1 |
protected function _toLogFile($str) { |
| 2 |
file_put_contents(APP_PATH . '/log',$str,FILE_APPEND); |
這兒,為了簡便,我就直接使用file_put_contents了,這個函數功能很強大啊,我特別喜歡~~
由於到目前還沒有講URL重新導向,轉寄請求等,暫時就直接顯示錯誤頁,所以又需要有一個輔助函數:
| 1 |
protected function _outputErrorPage() { |
| 2 |
header("content-type:text/html"); |
| 3 |
echo file_get_contents(APP_PATH . '/error.html'); |
因為要求代碼簡單,所以錯誤頁和記錄檔都直接寫死到項目根目錄中,如果你有興趣,可以自己試著將路徑寫在設定檔中,這個也不是很難的。
由於輔助函數已經寫完,所以其他兩個函數就很easy了:
| 1 |
public function printStack() { |
| 2 |
if(true === C('debug')) { |
| 3 |
echo parent::getTraceAsString(); |
| 5 |
$this->_toLogFile(parent::getTraceAsString()); |
| 6 |
$this->_outputErrorPage(); |
| 1 |
public function __toString() { |
| 2 |
if(true !== C('debug')) { |
| 3 |
$this->_toLogFile(parent::getTraceAsString()); |
| 4 |
$this->_outputErrorPage(); |
| 7 |
return parent::__toString(); |
當然,由於__toString要返回字串,而一旦throw一個異常,就會直接顯示出來異常資訊,為了在debug關閉之後不在頁面顯示異常資訊,所以就直接在此處exit了,當然,我目前沒有想到一個更好的辦法,所以建議使用printStack來做。
我這個異常類就是用來拋磚引玉的,所以如果你有什麼好的方法,請和我多多交流,互相學習,互相成長。
當然,現在只是定義了一個異常處理的基類,後面會寫很多關於異常的子類,真正使用的時候是調用其子類的。