이 글은 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
1.2 PHP 예외 기능
PHP
throw
) 예외가 포착될 수 있습니다. throw
는 자동으로 위쪽으로 던집니다.
throw
이후의 명령문은 실행되지 않습니다🎜🎜try< /code> 뒤에는 <code>catch
가 와야 합니다. 그렇지 않으면 구문 분석 오류 구문 분석 오류
🎜🎜🎜/** * 自定义异常类 * 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.........';
Php
는 다음과 같습니다. java
는 많은 예외 클래스를 제공하므로 많은 예외가 오류로 간주됩니다. 오류를 예외로 변경하려면 예외 객체 🎜🎜🎜PHP 내장 예외(예: 🎜PDOException
, SplFileObject</)를 수동으로 <code>throw
해야 합니다. code> 🎜자동으로 예외가 발생하고 다음 코드가 계속 실행될 수 있습니다. 🎜🎜🎜 🎜🎜🎜 🎜1.4 오류와 예외의 차이점🎜🎜1.4.1 예외 처리🎜🎜 예외가 발생하면 🎜throw
🎜🎜 이후의 코드는 계속 실행되지 않습니다🎜, PHP</ code> 일치하는 <code>catch
블록을 찾으려고 시도합니다. 예외가 catch되지 않고 해당 처리에 set_Exception_handler()
를 사용할 필요가 없으면 심각한 오류(🎜fatal error🎜)가 발생하고 "Uncaught Exception
이 발생합니다. "(잡히지 않은 예외) 오류 메시지. 🎜🎜1.4.2 예외의 기본 구문 구조🎜🎜 🎜try
🎜 - 예외를 처리해야 하는 코드는 잠재적인 가능성을 포착하기 위해 try
코드 블록 내에 배치되어야 합니다. 예외. 예외가 트리거되지 않으면 코드는 평소대로 계속 실행됩니다. 그러나 예외가 트리거되면 예외가 발생합니다. throw
- 예외를 트리거하는 방법을 지정합니다. 각각의 🎜try🎜 또는 🎜throw🎜 🎜는 반드시
🎜가 하나 이상의 🎜catch🎜와 일치해야 합니다. 여러 🎜catch🎜 블록을 사용하여 다양한 종류의 예외를 포착할 수 있습니다. catch
- 🎜catch🎜코드 블록은 예외를 포착하고 예외 정보가 포함된 객체를 생성합니다🎜🎜1.4.3 예외 다시 발생🎜🎜 가끔 예외가 발생하면 어쩌면 표준과 다르게 취급하고 싶습니다. 🎜catch🎜 블록에서 예외가 다시 발생할 수 있습니다. 예외를 다시 발생시키려면 try{}catch{}가 필요하며 catch 코드 블록에서는 예외를 직접 발생시킬 수 없습니다
. 🎜🎜 스크립트는 사용자에게 시스템 오류를 숨겨야 합니다. 시스템 오류는 프로그래머에게 중요할 수 있지만 사용자는 이에 관심이 없습니다. 사용자가 더 쉽게 사용할 수 있도록 사용자에게 친숙한 메시지를 사용하여 예외를 다시 발생시킬 수 있습니다. 예외: 프로그램 작동이 기대와 일치하지 않습니다.🎜오류: 오류가 저절로 발생합니다🎜
throw
🎜 문을 통해 발생하고 🎜catch
🎜를 통해 포착될 수 있습니다. 그렇지 않으면 치명적인 오류가 발생합니다. 🎜🎜toString
두 함수만 재정의할 수 있습니다🎜🎜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 #换行符
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!