1.前言
异常表示程序运行与自我预期不一致,与错误是两种概念,且异常必须被手动抛出。
代码分享:https://github.com/mtdgclub/tryCatch
1.1异常和错误区别
错误没办法在调用的时候向上传递,必须马上处理;异常则可以。
错误在触发的时候,必须对脚本做一个错误处理;异常可以自定义处理错误信息。
2.异常的基本语法结构
2.1基本语法代码块
try{ //代码段 }catch(Exception $e){ //捕捉异常并处理 }
举例:
<?php try{ $num2=0; if($num2==0){ throw new Exception("这是一个错误,0不能当除数"); } }catch(Exception $e){ echo $e->getMessage(); }
注意:PDO是有内置异常类的,比如PDO连接
try{ $pdo=new PDO("mysql:host=localhost;dbname=mysql",'root',''); var_dump($pdo); echo 'continue....'; }catch(PDOException $e){ echo $e->getMessage(); }
抛出异常,程序就不向下执行了
2.2自定义异常类
举例:
<?php class MyException extends Exception{ public function __construct($message, $code=0) { parent::__construct($message, $code); } public function __toString() { parent::__toString(); // TODO: Change the autogenerated stub $message="出现异常了,信息如下:<br />"; $message.="<p>".__CLASS__."[{$this->code}]:{$this->message}</p>"; return $message; } }
测试:
<?php require_once 'MyException.php'; //输出自定义格式 try{ echo '出现异常啊'; throw new MyException('测试自定义异常',3); }catch(MyException $e){ echo $e->getMessage(),'<hr/>'; echo $e; }
2.3 PHP多个catch进行异常捕获
<?php require_once 'MyException.php'; try{ throw new MyException('测试自定义异常'); }catch(MyException $e){ echo $e->getMessage(); }catch(Exception $e){ echo $e->getMessage(); } echo 'continue.....';
注意:测试捕获多个异常,建议把基类放在最后捕获
2.4案例:自定义文件写入异常处理类
<?php /** * 案例:自定义文件写入异常处理类 */ class FileException extends Exception { public function getDetails() { switch ($this->code) { case 0: return '没有提供文件'; break; case 1; return '文件不存在'; break; case 2: return '不是一个文件'; break; case 3: return '文件不可写'; break; case 4: return '非法文件的操作模式'; break; case 5: return '数据写入失败'; break; case 6: return '文件不能被关闭'; break; default: return '非法'; break; } } } class WriteData { private $_message = ''; private $_fp = null; public function __construct($filename = null, $mode = 'w') { $this->_message = "<br/>文件:{$filename} <br/>模式:{$mode}"; if (empty($filename)) { throw new FileException($this->_message, 0); } if (!file_exists($filename)) { throw new FileException($this->_message, 1); } if (!is_file($filename)) { throw new FileException($this->_message, 2); } if (!is_writable($filename)) { throw new FileException($this->_message, 3); } if (!in_array($mode, array('w', 'w+', 'a', 'a+'))) { throw new FileException($this->_message, 4); } $this->_fp = fopen($filename, $mode); } public function write($data) { if (!fwrite($this->_fp, $data . PHP_EOL)) { throw new FileException($this->_message, 5); } } public function close() { if (!fclose($this->_fp)) { throw new FileException($this->_message, 6); $this->_fp = null; } } }
测试及结果:
<?php require_once 'FileException.php'; try{ $fp=new WriteData('test.txt','w'); $fp->write('this is a test'); $fp->close(); echo "数据写入成功~"; }catch(FileException $e){ echo "出问题了".$e->getMessage()."<br/>详细信息如下:".$e->getDetails(); }
2.5记录与发送异常信息
<?php class LogExeception extends Exception { public function __construct($message, $code=0) { parent::__construct($message, $code); error_log($this->getMessage(),3,'testLogException.log'); } } //测试 try{ $link=mysqli_connect('localhost','root','root123','mysql'); if(!$link) { throw new LogExeception('数据库连接失败'); } }catch(LogExeception $e){ echo $e->getMessage(); }
测试及结果:
3.自定义异常处理器
使用set_exeption_handler()函数,该函数是设置一个用户定义的异常处理函数.
3.1第一次测试:不声明自定义异常处理器
<?php function exeption_handler_1($e) { echo '自定义的异常处理器1'; echo '异常信息:' . $e->getMessage(); } function exeption_handler_2($e) { echo '自定义的异常处理器2'; echo '异常信息:' . $e->getMessage(); } throw new Exception('测试');
如何处理没有被捕获的异常信息,在异常报错前声明自定义异常处理器。
3.2第二次测试:声明自定义异常处理器
<?php function exeption_handler_1($e){ echo '自定义的异常处理器1'; echo '异常信息:'.$e->getMessage(); } function exeption_handler_2($e){ echo '自定义的异常处理器2'; echo '异常信息:'.$e->getMessage(); } //声明自定义异常处理器 set_exception_handler('exeption_handler_1'); throw new Exception('测试');
//自定义异常处理器后面声明会覆盖前面声明 set_exception_handler('exeption_handler_1'); set_exception_handler('exeption_handler_2'); throw new Exception('测试');
//声明自定义异常处理器 set_exception_handler('exeption_handler_1'); set_exception_handler('exeption_handler_2'); //恢复到上一次定义过的异常处理函数 restore_exception_handler(); throw new Exception('测试');
注意:使用自定义异常处理器,调用了,程序就不再向下执行
3.3第三次测试:封装自定义异常处理器类
<?php /** * 定义一个类,捕获未捕获的异常信息 */ class ExceptionHandler { protected $_exception; protected $_logFile = 'ExceptionHandler.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); } public function __toString() { $message = <<<EOF <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>出现异常了,信息如下</h1> <p>刷新一下试试</p> <p><a href="mailto:747245429@qq.com">联系管理员看看747245429@qq.com</a></p> </body> </html> EOF; return $message; } } //测试 set_exception_handler(array('ExceptionHandler','handle')); throw new Exception('测试自定义异常处理器hello world');
放到try{}catch(){}中也可以调用到
4.像处理异常一样处理PHP错误
4.1使用PHP定义的错误异常类ErrorException
<?php //使用set_error_handler()函数将错误信息托管至ErrorException function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); } set_error_handler("exception_error_handler"); /* Trigger exception */ try{ echo gettype(); }catch(Exception $e){ echo $e->getMessage(); }
4.2自定义错误异常类
<?php /** * 自定义一个错误异常类 * Class ErrorToException */ class ErrorToException extends Exception { public static function handle($errno,$errstr){ throw new self($errstr,$errno); } } set_error_handler(array('ErrorToException','handle')); try{ echo $test; }catch(Exception $e){ echo $e->getMessage(); }
我们也可以设定处理级别,如下:
set_error_handler(array('ErrorToException','handle')); //只有警告级别才交给其处理 set_error_handler(array('ErrorToException','handle'),E_USER_WARNING|E_WARNING);
4.3发生错误如何重定向到404页面
<?php /** * 发生错误如何重定向到404页面 */ class ExceptionRedirectHandler{ protected $_exception; protected $logFile='redirectLog.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(); while(@ob_end_clean()); //PHP 实现307重定向的方式 header('HTTP/1.1 307 Temporary Redirect'); //发送一个报头,告诉浏览器当前页面不进行缓存,每次访问必读取最新数据 header('Cache-Control:no-cache,must-revalidate'); //内容过期时间 header('Expires:Sat,28 Mar 2015 13:28:48 GMT'); //强制重定向相对路径 header('Location:'.$self->redirect); exit(1); } public function log(){ error_log($this->_exception->getMessage().PHP_EOL,3,$this->logFile); } } set_exception_handler(array('ExceptionRedirectHandler','handle')); $link=mysqli_connect('localhost','root','root123','mysql'); if(!$link){ throw new Exception('数据库连接失败'); }
5.总结
通过本章回顾,再次认识到了异常和错误的区别、并了解了异常的基本语法、懂得如何制定一个异常类、并完成了自定义文件写入异常处理类案例、用error_log记录与发送异常信息和自定义异常处理器set_exeption_handler()函数使用及封装,希望通过本次学习,能够更好地掌握异常处理相关的函数和方法。
来源:站长