异常说明
异常时推荐的错误处理方式,传统的错误处理方式要判断并一层一层返回到调用点,如下所示:
<?php
class 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 '验证码创建失败';
}
通过上面代码我们发现处理错误时及其不方便,需要多个判断语句。下面是改用异常的处理方式。
<?php
class 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
的类。
<?php
class 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 |
<?php
class 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.php
bootstrap.php
composer.json
controller.php
index.php
文件内容
app\Exceptions\ValidateException.php
<?php
namespace App\Exceptions;
class ValidateException extends \Exception
{
public function render()
{
$_SESSION['VALIDATE_ERROR'] = '表单参数错误';
header('location:index.php');
}
}
app\Exceptions\ViewException.php
<?php
namespace App\Exceptions;
use App\Servers\View;
class ViewException extends \Exception
{
public function render()
{
View::make('error', ['error' => $this->getMessage()]);
}
}
app\Servers\Validate.php
<?php
namespace 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
<?php
namespace 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
<?php
session_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
<?php
include 'bootstrap.php';
use App\Servers\Validate;
use App\Servers\View;
Validate::make();
View::make('success');
index.php
<?php
namespace App;
include 'bootstrap.php';
use App\Servers\View;
View::make('index');