IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> PHP & 理解 Laravel 中 Errors & Exceptions (错误与异常) 的作用、使用 -> 正文阅读

[PHP知识库]PHP & 理解 Laravel 中 Errors & Exceptions (错误与异常) 的作用、使用

一、介绍

文本将从PHP原生错误/异常 讲解到 Laravel 错误/异常,耐心看完,相信你会有所收获。

1.1 什么是错误

在 PHP 中,最常见错误的级别有

错误类型解释
Deprecated比如 API 过期 ,属于低级错误
Notice变量未定义
Warning结果不符合逻辑,比如函数里面 $num + 100,但 $num 传递进来的是 ‘ab’
Fetal致命错误,直接终止运行后面的运行,比如调用不存在的函数
Prase最高级别错误,以上的都是运行期间报错,这里直接在语法解析期间报错。

给上面对应的错误类型举几个例子

<?php
// Notice 级别:未定义变量
echo($abc);

function foo($num){
  echo $num + 100;
}
// Warning 级别:传递错误的值
foo('hello');

// Fetal 级别:致命级别,导致后面的程序不在执行,比如调用不存在的函数
// throw new Error("你也可以手动通过 new error 抛出致命错误");
abc();

echo "这句话将不会被打印出来";

// Prase  级别:最高级别,以上都是运行期间错误,这里直接在语法解析期间错误
// 为了上面能正常运行,这里先注释掉
// echo ++;

在这里插入图片描述

另外,PHP 也提供了 set_error_handler ,此函数将会把所有把错误交给你接管,而 Laravel 正是利用了此函数进行重写,比如格式化输出、将所有错误以异常抛出去等等,具体怎么使用这里不在讲述,可参考文档。

1.2 什么是异常

PHP 是在 PHP5 后才引入异常的,每个语言对异常的理解各有不同,比如在 PHP 中 除 0 它是一个 warning 级别错误行为而不是异常,而在 JAVA 中它是属于异常行为。

$abc = 10 / 0;
// 10 / 0 属于报错 warning 行为,并不属于异常。
echo $abc;

所以很多时候异常都是由我们通过 if else 来手动控制抛出的,比如用户手机未输入

<?php
try {
	if (empty($_GET['phone'])) {
		throw new Exception('请输入手机号'); // 手动抛出
	}
} catch (Exception $e) {
	echo $e->getMessage(); // 接受异常传递过来的消息,我们直接打印。
}

在这里插入图片描述

注意:捕获异常需要用到 try / catch,如果直接在外部使用 throw new Exception,它将会是一个错误行为

throw new Exception('请输入手机号');

在这里插入图片描述

其实异常更多的作用是用来进行一些补救措施,比如数据库事务的回滚,
举个简单例子:用户提交订单

beginTransaction(); // 启动事务
try {
	DB::update('从数据库中扣掉商品库存');
	// 发现用户未输入手机号,我们手动抛出异常
	if (empty($_POST['phone'])) {
		throw new Exceptions('请输入手机');
	}
	commit(); // 提交事务:由于上面抛出异常,这里不会触发。
} catch(Exception $e) {
	rollback(); // 回滚事务:这里捕获到了异常,所以对扣掉库存这一操作进行回滚。
}

值得注意的是,在 PHP 7 以前,try/catch 是捕获不了错误的,比如调用不存在的函数

try {
	abc();
} catch(Exception $e) {
	echo '函数不存在' . $e->getMessage();
}

在这里插入图片描述

后来为了让部分错误能够捕获到,在 PHP 7 中引入了 Throwable ,可以说是 Exception 的升级版,但它只能对部分错误进行捕获,像下面的调用未知函数就可以捕获到。

try {
	abc();
	// 你也可以像 Exception 一样手动抛出 
	// throw new Throable("xxxx");
} catch (Throwable $e) {
	echo "函数不存在:" . $e->getMessage();
}

在这里插入图片描述

而像下面的访问未定义变量,依然还是捕获不了,直接一个报错行为。

try {
	echo $abc;
} catch (Throwable $e){
	echo "变量不存在" . $e->getMessage();
}

在这里插入图片描述

另外,PHP 也提供了 set_exception_handler ,次函数将所有异常都交给你接管, 显然 Laravel 也不会放过这个函数。

好了,接下来我们开始进入 Laravel

二、Laravel 中的错误与异常

理解了 PHP 中的基本错误/异常后,现在我们来开始使用 Laravel 中的错误/异常。

本文假设你已创建 Laravel 项目。

2.1 错误与异常的默认处理

我们首先抛出一个错误,看看在 Laravel 中会发生什么,假设我们有个 test 路由。

// route/web.php
use Illuminate\Support\Facades\Route;
Route::get('test', function(){
	echo $abc; // 打印不存在的变量。
});

接下来访问 http://localhost:8000/test ,输出如下:
在这里插入图片描述
可以看到,Laravel 展示的是一个美化过的错误页面。

另外我们也知道原生 try/catch 是无法捕获到未知变量这种错误行为的,但 Laravel 为我们做到了

use Illuminate\Support\Facades\Route;
Route::get('/test', function(){
	try  {
		echo $abc;
	} catch(Exception $e) {
		echo '变量不存在:'.$e->getMessage();
	}
});

在这里插入图片描述
很明显 Laravel 利用 set_error_handler 对错误进行了重写并以异常的形式抛出,这点值得称赞。

2.2 关于错误/异常发生后,Laravel 的日志记录问题

每次发生异常或者报错 Laravel 都会为我们写入日志文件里,下面是针对 try 内外的情况进行分析。

try 外

  1. 两者都被记录在 app/storage/logs 里面
echo $abc;
throw new Exception("抛出异常");

try 内

  1. 异常不会被记录,但可以手动调用 report() 进行记录,而错误会自动被记录。
try {
	throw new Exception("抛出异常"); // 不会被记录,只能在 catch 中手动记录。
	// echo $abc; // 会自动被记录
} catch (Exception $e) {
	report(); // 手动记录
	// .. do something
}

我们只需记得:使用 try/catch 后,权限交给用户,不使用则交给 Laravel

2.3 给 log 日志添加额外数据

每次发生异常或错误时我们想要给日志增加额外数据方便后续排查,需要怎么做?很简单,只需在 app/Exceptions/Handler.php 里面新增 context 方法进行添加即可,比如

// app/Exceptions/Handler.php =============
public function context() {
   return array_merge(parent::context(), [
        'user' => 'Cookcyq',
    ]);
}

在这里插入图片描述

2.4 自定义错误/异常页面

如上所知,默认情况下 Laravel 会自动返回一个美化过的页面,如果你不喜欢这种风格,Laravel 还提供了 $this->renderable 让你重写,我们来改造一下,依然是在 app/Exceptions/Handler.php 里面修改。

// app/Exceptions/Handler.php ==================
public function register(){
    // 重写
   $this->renderable(function(Throwable $e) {
       return response([
           'msg' => $e->getMessage(),
           'line' => $e->getLine(),
       ]);
   });
}

// route/web.php ==================
use Illuminate\Support\Facades\Route;
Route::get('/test', function(){
	echo $abc;
	// 或 throw new Exception("Something is wrong.");
});

现在我们来访问 http://localhost:8000/test
在这里插入图片描述

可以看到页面变成我们自定义的了,想要更多日志操作可参考官方文档:https://laravel.com/docs/9.x/errors

三、Laravel 自定义异常

由于上面的 $this->renderable 是全局性的,每个异常/错误都会触发,有时我们并不像这样做,而是仅针对某个功能,其它则按照 Laravel 默认模板正常显示,比如我们有个注册,如果注册有问题,就抛出注册异常,正好 Laravel 也为我们提供了这种能力。

  1. 首先在 app/Exceptions/目录下新增 RegisterException.php 文件,代码如下:
<?php
namespace App\Exceptions;
 
use Exception;
class RegisterException extends Exception
{
    /**
     * RegisterException 添加日志额外内容,可与全局 context 累加。
     */
    public function context() {
      return ['myException' => 'Cookcyq'];
    }
  	
  	/* 自定义响应内容 */
    public function render($request) {
      return response([
        'msg' => $this->getMessage()
      ]);
    }
}
  1. route/web.php 代码如下
use Illuminate\Support\Facades\Route;
use App\Exceptions\RegisterException;
Route::get('/test', function(){
	throw new RegisterException("Please make sure your account or password are correct.");
});

效果
在这里插入图片描述

四、业务案例

在实际业务中,假如我们是 API 提供者,我们需要对传递进来的参数不正确、残缺等情况进行响应处理,这个时候我们就可以利用自定义 Exception。

  1. 还是老样子,首先在 app/Exceptions/ 新建 MyException.php 文件,代码如下
<?php
namespace App\Exceptions;
 
use Exception;
class MyException extends Exception
{
    public function render($request) {
      $data = [
        'msg' => $this->getMessage(),
        'status' => $this->code
      ];
      // JSON_UNESCAPED_UNICODE 解决中文变成 unicode 问题。
      return response()->json($data)->setEncodingOptions(JSON_UNESCAPED_UNICODE);
    }
}
  1. 定义 /login 路由,代码如下
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Exceptions\MyException;
Route::get('/login', function(Request $request){
	if (empty($request['phone'])) {
		throw new MyException("请输入手机", -10000);
	}
	if (empty($request['password'])) {
		throw new MyException("请输入密码", -10000);
	}
	return response([
		'msg' 		=> '登录成功',
		'status' 	=> 10000,
	]);
});

此时我们访问:http://localhost:8000/login
在这里插入图片描述

访问 http://localhost:8000/login?phone=10086&password=secret
在这里插入图片描述
怎么样,异常的处理是不是很简单?

总结

Laravel 利用了 set_error_handler / set_exception_handler 对错误/异常进行了重写,给开发者带来了许多便利之处。

希望本文能让你对 PHP 原生和 Laravel 中错误/异常的区别有一定的认识。

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2022-03-11 21:55:31  更:2022-03-11 21:56:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 15:43:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计