技术标签: 异常处理 错误处理 thinkphp6 thinkphp tp6 Thinkphp
一般项目中路由分为返回模板引擎页面
和返回api接口json数据
,两种方式异常需要返回不同的内容,如果是模板引擎页面遇到异常需要返回错误页面,如果是api接口遇到异常需要返回json数据。
开发模式和上线模式应该返回不同的内容,开发模式应该尽可能返回具体的错误信息,上线模式则不能返回具体的错误信息,一般显示“服务器错误,请稍后重试”类似友好的提示,而不是显示一堆报错代码(既不友好又不安全)。
如果有更好的方法,欢迎提出意见。
在访问路由时,若控制器不对,需要使用空控制器
拦截报错。
方法找不到可以修改app目录下的BaseController控制器重写__call方法。
自定义拦截报错信息,可以使用Provider自定义错误处理类,重写render方法,根据不同的错误返回不同的数据。
同第3点。
(1)
.env
文件定义APP_DEBUG
区分开发模式和线上模式,true表示开发模式,false表示线上模式:
APP_DEBUG = true
(2) 在
app/common.php
文件定义api
返回的数据格式:
function show($status, $message = 'error', $data = [], $httpStatus = 200){
$result = [
"status" => $status,
"message" => $message,
"result" => $data
];
return json($result, $httpStatus);
}
(3) 在当前应用下新建一个provider.php,并指定自定义异常处理类:
<?php
// 容器Provider定义文件
return [
'think\exception\Handle' => 'app\\admin\\exception\\Http',
];
(4) 定义状态码配置,可以在
config
文件夹下新建status.php
添加相应的状态码配置:
<?php
return [
"success" => 1,
"error" => 0,
"http_status" => [
"not_found" => 404,
"validate_error" => 422,
"internal_error" => 500
]
];
(5) 准备错误页面(404,500等)
在app/controller
目录新建Error
类(文件名固定为Error
):
这里需要注意的是,多应用的控制器应该定义在应用文件夹里,这里定义在app目录是为了作用于app下全部应用。
<?php
namespace app\controller;
class Error
{
public function __call($name, $arguments)
{
if(request()->isAjax()){
return show(config("status.error"), env('app_debug') ? "控制器{
$name}找不到" : '当前请求资源不存在,请稍后再试', [], config("status.http_status.not_found"));
}else{
return view(root_path() . 'public/error/admin/404.html', ['e' => env('app_debug') ? "控制器{
$name}找不到" : '当前请求资源不存在,请稍后再试'], config("status.http_status.not_found"));
}
}
}
在app/BaseController.php
控制器添加 __call
方法:
public function __call($name, $arguments)
{
if(request()->isAjax()){
return show(config("status.error"), env('app_debug') ? "找不到{
$name}方法" : '当前请求资源不存在,请稍后再试', [], config("status.http_status.not_found"));
}else{
return view(root_path() . 'public/error/admin/404.html', ['e' => env('app_debug') ? "{
$name}方法找不到" : '当前请求资源不存在,请稍后再试'], config("status.http_status.not_found"));
}
}
app\\admin\\exception\\Http
:
<?php
namespace app\admin\exception;
use ErrorException;
use Exception;
use InvalidArgumentException;
use ParseError;
use PDOException;
use think\exception\ClassNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\RouteNotFoundException;
use think\Response;
use Throwable;
use TypeError;
class Http extends Handle
{
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
$returnCode = config("status.error");
$returnMessage = "系统异常,请稍后再试";
$returnData = [];
$httpStatus = 500;
if($e instanceof BusinessException){
// 自定义添加的业务异常
$returnMessage = $e->getMessage();
$httpStatus = config("status.http_status.business_error");
}else if($e instanceof ValidateException){
$returnMessage = $e->getError();
$httpStatus = config("status.http_status.validate_error");
}else if (($e instanceof ClassNotFoundException || $e instanceof RouteNotFoundException) || ($e instanceof HttpException && $e->getStatusCode() == 404)) {
$returnMessage = env('app_debug') ? $e->getMessage() : '当前请求资源不存在,请稍后再试';
$httpStatus = config("status.http_status.not_found");
}else if ($e instanceof Exception || $e instanceof PDOException || $e instanceof InvalidArgumentException || $e instanceof ErrorException || $e instanceof ParseError || $e instanceof TypeError || ($e instanceof HttpException && $e->getStatusCode() == 500)) {
$returnMessage = env('app_debug') ? $e->getMessage() : '系统异常,请稍后再试';
$httpStatus = config("status.http_status.internal_error");
}
if(request()->isAjax()){
return show($returnCode, $returnMessage, $returnData, $httpStatus);
}else{
if($httpStatus == config("status.http_status.not_found")){
$errorUrl = 'public/error/admin/404.html';
}else{
$errorUrl = 'public/error/admin/error.html';
}
return view(root_path() . $errorUrl, ['e'=>$returnMessage], $httpStatus);
}
}
}
以上代码中返回的错误信息e
,需要在错误页面(404,error)显示:
<p class="error-message">{$e ?? ''}</p>
异常检测分浏览器页面访问异常
和api接口返回异常
,还需要检查开发模式
和线上模式
。
Tips:
api
接口可以使用Postman
工具模拟,添加Headers
:
Content-Type
为application/x-www-form-urlencoded
X-Requested-With
为xmlhttprequest
(博主比较懒就不贴截图了,但是都测试过,同志们自己试一下,算了还是贴一张吧)
️重磅推荐:免费商用电商系统
想白嫖整个电商系统用来商用?
想有自己的商城实现财富自由?
想学习最佳实践提升自己技术?
快来进入 传送门 ,开源免费、完整示例带你快速入门,轻松二开,走上人生巅峰!
文章浏览阅读6.6k次,点赞2次,收藏8次。水墨效果,素材简陋:文章参考http://gad.qq.com/article/detail/18724,原理可以看这位大佬的文章,我就贴上自己工程源码:https://download.csdn.net/my_unity3d shader 水墨动画
文章浏览阅读1.1k次,点赞2次,收藏17次。在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括招聘信息管理系统的网络应用,在外国招聘信息管理系统已经是很普遍的方式,不过国内的线上管理系统可能还处于起步阶段。招聘信息管理系统具有招聘信息管理功能的选择。_java人力资源管理系统招聘管理
文章浏览阅读1.3w次,点赞5次,收藏20次。几个基础材料(源:http://jwc.seu.edu.cn/zq/signal/new/importent/zhang5_6/feng.htmhttp://jwc.seu.edu.cn/zq/signal/new/importent/zhang5_6/harvard.htmhttp://dingjun.net/dingjun/html/14/84FB43402106C575.html_冯诺依曼曼指令和数据区分
文章浏览阅读428次。客户端定时每X秒(推荐小于60秒)向服务端发送特定数据(任意数据都可),服务端设定为X秒没有收到客户端心跳则认为客户端掉线,并关闭连接触发onClose回调。当需要服务端定时给客户端发送心跳数据时, $gateway->pingData设置为服务端要发送的心跳请求数据,心跳数据是任意的,只要客户端能识别即可。当设置为服务端主动发送心跳时,如果客户端最近有发来数据,那么证明客户端存活,服务端会省略一个心跳,下个心跳大约1.5*$gateway->pingInterval秒后发送。心跳检测时间间隔 单位:秒。_netty 服务端心跳检测
文章浏览阅读535次。下面有两个大的模块:一个是SPI总线驱动的分析 (研究了具体实现的过程)另一个是SPI总线驱动的编写(不用研究具体的实现过程)SPI总线驱动分析 1 SPI概述 SPI是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口,是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应_linux spi驱动总线分析
文章浏览阅读511次。Nginx,nginx-rtmp-module-master搭建直播平台_nginx-rtmp-module-master
文章浏览阅读1k次。访问springcloud工程, springboot版本为2.1.15 ,使用域名访问接口报400但是直接用ip不报错。发现是集成的tomcat版本不支持域名下划线。大约是8.5.31以后的版本不支持带下划线的域名,但是也没办法降低版本了,会有很多冲突。先搁置。..._springboot the character [_] is never valid in a domain name.
文章浏览阅读420次。QEMU 运行 RISC-V 64 位 Linux_qemu启动riscv环境
文章浏览阅读4.3k次。聊这个话题,我表示又蛋疼了!你想看么?还没写过这么有争议的话题,有点小小的不安!一年有多长?让我来掐指算一算:1年=365天(今年是366天)=多少小时呢?前方高能,等我去写个程序算一下!还用写程序吗?早有人写好了!有多少分有多少秒,又有多少毫秒呢?我们只需要选择一下单位就好了,结果是:1年(yr)=31536000000毫秒(ms)为什么聊这个话题?蛋当然不可能说疼就疼了!水是有源的,树是有根的_程序员 一年多少秒
文章浏览阅读745次。第一步 : 下载git 进入git官网 https://git-scm.com/download/win 下载git软件. 我这里演示安装Git-2.16.1.4-64-bit.exe 1 . 运行 Git-2.16.1.4-64-bit.exe 点击Next 2. 选择安装目录 点击Next 3. 第二步 : 安装码云插件第三步 : 配..._idea 使用码云维护项目
文章浏览阅读186次。实现代码:<!DOCTYPE html><html><head> <meta charset="UTF-8"> <meta http-equiv="Cache-Control" content="no-store" /> <meta http-equi_百度地图js api地址搜索
文章浏览阅读986次。VSTO(Visual Studio Tools for Office)是微软开发的一种用于创建Microsoft Office应用程序的工具集,它可以让开发者在Microsoft Office应用程序中集成自己的.NET应用程序。VSTO还提供了一些特殊的工具和库,使得开发人员可以更方便地管理Microsoft Office应用程序的生命周期、访问Microsoft Office应用程序的API和对象模型、处理Microsoft Office应用程序的事件和异常等。Office版本:2016 32位。_office开发版本号与vsto