この記事では、PHP プログラマーが遭遇したエラーと例外を紹介します。必要な友人は参照してください
try { // 需要进行异常处理的代码段; throw 语句抛出异常; }catch( Exception $e ) { ... } catch( Exception $e ) { // 处理异常 } contine.....
キャッチされない例外は致命的なエラーを報告します: Fatal error:UncaughtException....
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
1.2 PHP 例外機能
PHP
throw
) 例外をキャッチできます。
throw
は自動的に上向きにスローします
throw
の後のステートメントは実行されません🎜🎜try の後には <code>catch
が続く必要があります。そうでない場合、解析エラー Parse error
🎜🎜🎜/** * 自定义异常类 * 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.........';🎜1.3 PHP 組み込み例外🎜🎜
Php
はjava
とは異なり、多くの例外クラスが提供されるため、多くの例外がエラーとみなされます。エラーを例外に変更するには、例外オブジェクト 🎜🎜🎜PHP 組み込み例外 (🎜PDOException
、SplFileObject) を手動で <code>throw
する必要があります。 code> 🎜 は自動的に例外をスローし、次のコードは実行を続行できます。 🎜🎜🎜 🎜🎜🎜 🎜1.4 エラーと例外の違い🎜🎜1.4.1 例外処理🎜🎜 例外がスローされると、🎜throw
🎜🎜 以降のコードは実行を継続しません🎜, PHP code> は、一致する <code>catch
ブロックの検索を試みます。例外がキャッチされず、対応する処理に set_Exception_handler()
を使用する必要がない場合、重大なエラー (🎜致命的エラー🎜) が発生し、「Uncaught Exception
」が発生します。 " (キャッチされない例外) エラー メッセージ。 🎜🎜1.4.2 例外の基本構文構造🎜🎜 🎜try
🎜 - 例外を処理する必要があるコードは、潜在的な例外をキャッチするために try
コード ブロック内に配置する必要があります。例外がトリガーされない場合、コードは通常どおり実行を続行します。ただし、例外がトリガーされると、例外がスローされます。throw
- 例外をトリガーする方法を指定します。それぞれの 🎜try🎜 または 🎜throw🎜 🎜must
🎜 は、少なくとも 1 つの 🎜catch🎜 に対応しています。複数の 🎜catch🎜 ブロックを使用して、さまざまな種類の例外をキャッチできます。 catch
- 🎜catch🎜 コード ブロックは例外をキャッチし、例外情報を含むオブジェクトを作成します🎜🎜1.4.3 例外を再スローします🎜🎜 例外がスローされると、おそらく、標準とは異なる扱いをしたい。例外は 🎜catch🎜 ブロックで再度スローできます。 例外を再度スローするには try{}catch{} が必要であり、例外を catch コード ブロックで直接スローすることはできないことに注意してください。
🎜🎜 スクリプトはシステムエラーをユーザーから隠す必要があります。システム エラーはプログラマにとって重要かもしれませんが、ユーザーはそれらに興味がありません。ユーザーにとって使いやすいように、わかりやすいメッセージを付けて例外を再度スローできます。 例外: プログラムが期待と矛盾して実行される🎜エラー: エラーはそれ自体によって引き起こされる🎜
throw
🎜 ステートメントによってスローされ、🎜catch
🎜 によってキャッチされます。キャッチされない場合は、致命的なエラーが発生します。 🎜🎜toString
の 2 つの関数のみ🎜🎜catch
が複数ある場合、通常、Exception
基本クラスが最後に配置されます。🎜 基本クラスはカスタム例外クラスで定義されたメソッドを呼び出すことができます🎜。 🎜 🎜🎜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 #换行符🎜2.2 ヒント🎜
Exception_Observer.php /** * 给观察者定义规范 * * Interface Exception_Observer */ interface Exception_Observer { public function update(Observable_Exception $e); }🎜 エラーログ情報を記録する方法:🎜
(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 プログラマーが遭遇するエラーと例外 パート 2: 例外の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。