异常说明
异常是推荐的错误处理方式,传统的错误处理方式要判断并一层一层返回到调用点,如下所示:
<?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...cache触发。
try{
...
}catch(){
...
}
在 try
代码块中对出现的错误可以抛出异常,下面是手动抛出异常的方法。
throw new Exception($message,$code)
catch
用于接收异常,可以设置多个catch
代码块,参数为 Exception
类或继承于 Exception
的类。
<?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
文件内容
appExceptionsValidateException.php
<?php
namespace AppExceptions;
class ValidateException extends Exception
{
public function render()
{
$_SESSION['VALIDATE_ERROR'] = '表单参数错误';
header('location:index.php');
}
}
appExceptionsViewException.php
<?php
namespace AppExceptions;
use AppServersView;
class ViewException extends Exception
{
public function render()
{
View::make('error', ['error' => $this->getMessage()]);
}
}
appServersValidate.php
<?php
namespace AppServers;
use AppExceptionsValidateException;
class Validate
{
public static function make()
{
$_SESSION['VALIDATE_ERROR'] = '';
if (empty($_POST['title'])) {
throw new ValidateException('表单错误');
}
}
}
appServersView.php
<?php
namespace AppServers;
use AppExceptionsViewException;
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;
}
}
appviewerror.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>
appviewindex.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>
appviewerror.blade.php
<h1>操作成功</h1>
appootstrap.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": "hd/app",
"authors": [
{
"name": "houdunren.com",
"email": "2300071698@qq.com"
}
],
"autoload": {
"psr-4": {
"App\": "."
}
},
"require": {}
}
controller.php
<?php
include 'bootstrap.php';
use AppServersValidate;
use AppServersView;
include 'vendor/autoload.php';
// try {
Validate::make();
View::make('success');
// } catch (ValidateException $e) {
// $e->render();
// } catch (ViewException $e) {
// $e->render();
// }
index.php
<?php
namespace App;
include 'bootstrap.php';
use AppServersView;
View::make('index');