本篇文章介紹的內容是PHP程式設計師遇到的錯誤與異常中的異常問題,現在分享給大家,有需要的朋友可以參考一下
try { // 需要进行异常处理的代码段; throw 语句抛出异常; }catch( Exception $e ) { ... } catch( Exception $e ) { // 处理异常 } contine.....
未被捕獲的異常會報致命錯誤:Fatal error:Uncaught exception.....
PHP
不會主動捕捉異常,需要程式中主動拋出(throw
)異常,才能捕捉。
throw
會自動向上拋出
#throw
之後的語句不會執行
try
後面必須有catch
,否則解析錯誤Parse error
try{ $num1=3; $num2=0; if($num2==0){ throw new Exception('0不能当作除数'); echo 'this is a test';//看不到 }else{ $res=$num1/$num2; } }catch(Exception $e){ echo $e->getMessage(); }
Php
不像java
提供了很多異常類,所以很多異常都會當成錯誤。要變錯誤為拋出異常,需要手動throw
異常物件
#PHP內建異常如:PDOException
、SplFileObject
可以自動拋出異常,後面的程式碼可以繼續執行。
當例外被拋出,throw
##後的程式碼不會繼續執行#,PHP 會嘗試尋找符合的
catch 程式碼區塊。如果異常沒有被捕獲,而且又沒用使用
set_exception_handler() 作相應的處理的話,那麼將發生一個嚴重的錯誤(
致命錯誤),並且輸出“ Uncaught Exception” (未捕獲異常)的錯誤訊息。
try - 需要進行例外處理的程式碼應該放入try
程式碼區塊內,以便捕獲潛在的異常。如果沒有觸發異常,則程式碼將照常繼續執行。但如果例外被觸發,會拋出一個例外
throw - 這裡規定如何觸發例外。每一個
try或 throw 必須對應至少一個 catch。使用多個catch程式碼區塊可以捕捉不同種類的例外。
catch -
catch程式碼區塊會擷取例外,並建立一個包含例外訊息的物件
catch 程式碼區塊中再次拋出異常。 注意再次拋出異常需要try{}catch{},不能直接在catch程式碼區塊中throw異常。
簡言:如果拋出了異常,就必須捕捉它。
異常:程式運行與預期不太一致錯誤:觸發的是本身的錯誤
throw語句拋出異常,透過catch
捕獲異常,如果未捕獲會產生致命錯誤。
只能重寫建構子和toString兩個函數
catch 時,一般
Exception基底類別放在最後,
基底類別可以呼叫自訂例外類別定義的方法
/** * 自定义异常类 * Class MyException */ class MyException extends Exception { public function __construct($message = "", $code = 0, Throwable $previous = null) { parent::__construct($message, $code, $previous); } public function __toString() { $message = "<h2>出现异常了,信息如下</h2>"; $message .= "<p>".__CLASS__."[{$this->code}]:{$this->message}</p>"; return $message; } public function test() { echo 'this is a test'; } public function stop() { exit('script end...'); } //自定义其它方法 } try{ echo '出现异常啦'; throw new MyException('测试自定义异常'); }catch (MyException $exception){ echo $exception->getMessage(); echo $exception; } //会继续执行 echo 'continue.........';
try{ throw new MyException('测试自定义异常'); }catch (Exception $exception){ echo $exception->getMessage(); $exception->test(); } catch (MyException $exception){ echo $exception->getMessage(); }
//将错误用错误抑制符吸收,然后抛出异常 If(@!fwrite($filename,$data)) throw new exception(自定义异常) PHP_EOL #换行符
(1) :file_put_contents(LOG_PATH.'error.log';, '错误信息'.' '.date('Y-m-d H:i:s')."\r\n", FILE_APPEND);
(2) :error_log('错误信息'.' '.date('Y-m-d H:i:s')."\r\n",3,LOG_PATH.'error.log');
Exception_Observer.php /** * 给观察者定义规范 * * Interface Exception_Observer */ interface Exception_Observer { public function update(Observable_Exception $e); }
Observable_Exception.php /** * 定义观察者 * Class Observable_Exception */ class Observable_Exception extends Exception { //保存观察者信息 public static $_observers = array(); public static function attach(Exception_Observer $observer) { self::$_observers[] = $observer; } public function __construct($message = "", $code = 0, Throwable $previous = null) { parent::__construct($message, $code, $previous); $this->notify(); } public function notify() { foreach (self::$_observers as $observer) { $observer->update($this); } } }
Logging_Exception_Observer.php /** * 记录错误日志 * Class Logging_Exception_Observer */ class Logging_Exception_Observer implements Exception_Observer { protected $_filename = __DIR__.'/error_observer.log'; public function __construct($filename = null) { if ($filename!==null && is_string($filename)){ $this->_filename = $filename; } } public function update(Observable_Exception $e) { $message = "时间:".date('Y:m:d H:i:s',time()).PHP_EOL; $message.= "信息:".$e->getMessage().PHP_EOL; $message.= "追踪信息:".$e->getTraceAsString().PHP_EOL; $message.= "文件:".$e->getFile().PHP_EOL; $message.= "行号:".$e->getLine().PHP_EOL; error_log($message,3,$this->_filename);//写到日志中 } }
test.php /** *测试 */ header('content-type:text/html;charset=utf-8'); require_once 'Exception_Observer.php'; require_once 'Logging_Exception_Observer.php'; require_once 'Observable_Exception.php'; Observable_Exception::attach(new Logging_Exception_Observer()); class MyException extends Observable_Exception{ public function test() { echo 'this is a test'; } } try{ throw new MyException('出现了异常!'); }catch (MyException $exception){ echo $exception->getMessage(); }
类似set_error_handler
接管系统的错误处理函数,set_exception_handler
接管所有没有被catch
的异常
restore_exception_handler
同restore_error_handler
一样,本质上应该说从异常/错误处理函数栈中弹出一个。比如有一个异常处理函数,弹出一个的话,就没有异常处理函数,如果有异常没有捕获,会交由错误处理函数,如没有错误处理函数,异常最终会有系统错误处理函数处理。如果设置了2个异常处理函数,弹出一个,会交由下面一个异常处理函数处理。
/** * 自定义异常函数处理器 */ header('content-type:text/html;charset=utf-8'); function exceptionHandler_1($e) { echo '自定义异常处理器1<br/>函数名:'.__FUNCTION__.PHP_EOL; echo '异常信息:'.$e->getMessage(); } function exceptionHandler_2($e) { echo '自定义异常处理器2<br/>函数名:'.__FUNCTION__.PHP_EOL; echo '异常信息:'.$e->getMessage(); } set_exception_handler('exceptionHandler_1'); //set_exception_handler('exceptionHandler_2'); //恢复到上一次定义过的异常处理函数,即exceptionHandler_1 //restore_exception_handler(); //致命错误信息 //restore_exception_handler(); throw new Exception('测试自定义异常处理器'); //自定义异常处理器,不会向下继续执行,因为throw之后不会再继续执行;try{} catch{}之后,会继续执行 //回顾:自定义错误处理器会继续执行代码,而手动抛出的错误信息不会继续执行 echo 'test';
/** * 自定义异常类处理器 * Class ExceptionHandler */ class ExceptionHandler { protected $_exception; protected $_logFile = __DIR__.'/exception_handle.log'; public function __construct(Exception $e) { $this->_exception = $e; } public static function handle(Exception $e) { $self = new self($e); $self->log(); echo $self; } public function log() { error_log($this->_exception->getMessage().PHP_EOL,3,$this->_logFile); } /** * 魔术方法__toString() * 快速获取对象的字符串信息的便捷方式,直接输出对象引用时自动调用的方法。 * @return string */ public function __toString() { $message = <<<EOF <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>出现异常了啊啊啊啊</h1> </body> </html> EOF; return $message; } } set_exception_handler(array('ExceptionHandler','handle')); /** * try catch不会被自定义异常处理!!!! */ try{ throw new Exception('this is a test'); }catch (Exception $exception) { echo $exception->getMessage(); } throw new Exception('测试自定义的异常处理器');
异常:
自定义异常处理器不会向下继续执行,因为throw
之后不会再继续执行try{} catch{}
之后,会继续执行错误:
自定义错误处理器会继续执行代码,而手动抛出的错误信息不会继续执行
/** * 方式一:ErrorException错误异常类 * @param $errno * @param $errstr * @param $errfile * @param $errline * @throws ErrorException */ function exception_error_handler($errno,$errstr,$errfile,$errline){ throw new ErrorException($errstr,0,$errno,$errfile,$errline); } set_error_handler('exception_error_handler'); try{ echo gettype(); }catch (Exception $exception){ echo $exception->getMessage(); }
/** * 方式二:自定义异常类 * Class ErrorToException */ //显示所有的错误 error_reporting(-1); class ErrorToException extends Exception{ public static function handle($errno,$errstr) { throw new self($errstr,0); } } set_error_handler(array('ErrorToException','handle')); set_error_handler(array('ErrorToException','handle'),E_USER_WARNING|E_WARNING); try{ echo $test;//notice,不会被处理 echo gettype();//warning //手动触发错误 trigger_error('test',E_USER_WARNING); }catch (Exception $exception){ echo $exception->getMessage(); }
header('Content-type:text/html;charset=utf-8'); class ExceptionRedirectHandler{ protected $_exception; protected $_logFile = __DIR__.'redirect.log'; public $redirect='404.html'; public function __construct(Exception $e){ $this->_exception=$e; } public static function handle(Exception $e){ $self=new self($e); $self->log(); // ob_end_clean()清除所有的输出缓冲,最后没有缓存的时候会产生通知级别的错误 while(@ob_end_clean()); header('HTTP/1.1 307 Temporary Redirect'); //临时重定向 header('Cache-Control:no-cache,must-revalidate');//no-cache强制向源服务器再次验证,must-revalidate可缓存但必须再向源服务器进行确认 header('Expires: Sat, 28 Mar 2016 13:28:48 GMT'); //资源失效的时间 header('Location:'.$self->redirect); //跳转 } public function log(){ error_log($this->_exception->getMessage().PHP_EOL,3,$this->_logFile); } } set_exception_handler(array('ExceptionRedirectHandler','handle')); $link=@mysqli_connect('127.0.0.1','root','1234561'); if(!$link){ throw new Exception('数据库连接出错啦'); }
完!
参考课程视频:那些年你遇到的错误与异常
相关推荐:
以上是PHP程式設計師遇到的錯誤與異常下篇之異常的詳細內容。更多資訊請關注PHP中文網其他相關文章!