异常说明
异常时推荐的错误处理方式,传统的错误处理方式要判断并一层一层返回到调用点,如下所示:
<?phpclass Code{protected $len;public function make(int $len){$this->len = $len;if ($this->line() === false) {return false;}}public function line(){if ($this->len > 5) {return false;}}}$code = new Code;if ($code->make(10) === false) {echo '验证码创建失败';}
通过上面代码我们发现处理错误时及其不方便,需要多个判断语句。下面是改用异常的处理方式。
<?phpclass Code{protected $len;public function make(int $len){$this->len = $len;$this->line();}public function line(){if ($this->len > 5) {throw new Exception('长度不能超过五位');}}}try {$code = new Code;$code->make(10);} catch (Exception $e) {echo $e->getMessage();}
基本使用
try/catch
PHP 需要手动抛出异常,这与其他语言不同,异常使用 try…catch 触发。
try{...}catch(){...}
在 try 代码块中对出现的错误可以抛出异常,下面是手动抛出异常的方法。
throw new Exception($message,$code)
catch 用于接收异常,可以设置多个 catch 代码块,参数为 Exception 类或继承于 Execption 的类。
<?phpclass ValidateException extends Exception{ }try {throw new ValidateException('is exception', 403);} catch (ValidateException $e) {echo 'httpException' . $e->getMessage() . ';code:' . $e->getCode();} catch (Exception $e) {echo $e->getMessage();} finally {echo '无论是否抛出异常都将执行' . ';code:' . $e->getCode();;}
finally
finally 需要放在 catch 后, finally 无论是否抛出异常都会执行。
...} catch (Exception $e) {echo $e->getMessage();} finally {echo '无论是否抛出异常都将执行';}...
Throwable
异常和部分错误实现了 Throwable 接口。
Exception implements Throwable {...}
部分错误也实现了 Throwable 接口
Error implements Throwable {...}
比如以下错误:
- ArithmeticError 数学运算错误
- DivisionByZeroError 除数为0的错误
- ParseError 解析代码时发生错误如调用
eval函数时 - TypeError 函数参数类型错误,函数返回值错误
异常类
基类方法
PHP 为异常处理提供了基础类 Exception ,Exception 类可用方法如下:
| 方法 | 说明 | 重写 |
|---|---|---|
| getFile | 产生异常错误的文件 | NO,final |
| getCode | 错误码 | NO,final |
| getLine | 错误行号 | NO,final |
| getMessage | 错误信息 | NO,final |
| __toString | 对象转字符串后输出内容 | YES |
<?phpclass ValidateException extends Exception{//对象转字符串时执行的魔术方法public function __toString(){return $this->getFile();}}try {throw new ValidateException('is exception', 403);} catch (ValidateException $e) {echo "文件:" . $e->getFile() . "<hr/>";echo "消息:" . $e->getMessage() . "<hr/>";echo "错误码:" . $e->getCode() . "<hr/>";echo "错误行:" . $e->getLine() . "<hr/>";echo $e . "<hr/>";}
异常实例
实际开发中需要根据不同业务创建处理错误的异常类,推荐使用异常来处理错误而不是 PHP 的错误处理机制。
自定义异常
下面是通过实例讲解自定义异常的使用方法。
目录结构
app-- Exceptions-- ValidateException.php-- ViewException.php-- Servers-- Validate.php-- View.php-- vendor-- view-- error.blade.php-- index.blade.php-- success.blade.phpbootstrap.phpcomposer.jsoncontroller.phpindex.php
文件内容
app\Exceptions\ValidateException.php
<?phpnamespace App\Exceptions;class ValidateException extends \Exception{public function render(){$_SESSION['VALIDATE_ERROR'] = '表单参数错误';header('location:index.php');}}
app\Exceptions\ViewException.php
<?phpnamespace App\Exceptions;use App\Servers\View;class ViewException extends \Exception{public function render(){View::make('error', ['error' => $this->getMessage()]);}}
app\Servers\Validate.php
<?phpnamespace App\Servers;use App\Exceptions\ValidateException;class Validate{public static function make(){$_SESSION['VALIDATE_ERROR'] = '';if (empty($_POST['title'])) {throw new ValidateException('表单错误');}}}
app\Servers\View.php
<?phpnamespace App\Servers;use App\Exceptions\ViewException;class View{public static function make(string $tpl, array $vars = []){$file = 'view/' . $tpl . '.blade.php';if (!is_file($file)) {throw new ViewException($file . '模板不存在');}include $file;}}
app\view\error.blade.php
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title></head><body><h1><?php echo $vars['error'];?></h1></body></html>
app\view\index.blade.php
<?php if(isset($_SESSION['VALIDATE_ERROR'])):?><?php echo $_SESSION['VALIDATE_ERROR'];?><?php endif;?><form method="post" action="controller.php"><input type="text" name="title"><button>提交</button></form>
app\view\success.blade.php
<h1>操作成功</h1>
app\bootstrap.php
<?phpsession_start();include 'vendor/autoload.php';class Boot{public function init(){set_exception_handler([$this, 'exception']);}public function exception($e){if (method_exists($e, 'render')) {$e->render();}}}(new Boot)->init();
composer.json
{"name": "14778/app","authors": [{"name": "ixysec","email": "1477821088@qq.com"}],"autoload": {"psr-4": {"App\\": "."}},"require": {}}
controller.php
<?phpinclude 'bootstrap.php';use App\Servers\Validate;use App\Servers\View;Validate::make();View::make('success');
index.php
<?phpnamespace App;include 'bootstrap.php';use App\Servers\View;View::make('index');
