Laravel8异常返回自定义json
相关环境:PHP7.4 + Laravel8.83.8
背景:本人是前后端分离的情况,最近和前端同学调接口,当遇到异常:比如Exception的异常。运行接口地址是一个页面类型错误(如下图):
但是经理并不想以页面的方式给用户看,认为不太妥当,他要求:和正常接口返回一样以json数据方式返回给前端,前端提示相关错误。
比如我模拟异常,在控制器写了这行代码:
<?php
namespace App\Http\Admin\User;
use App\Http\Admin\Controller;
class UserController extends Controller
{
public function test()
{
throw new \Exception("出bug啦");
}
}
那么laravel框架是支持这种做法的,具体步骤如下:
在app\Exceptions\Handler.php里面,有个render方法,他的作用就是:渲染异常为 HTTP 响应
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
public function render($request, Throwable $e)
{
return response()->json([
'code' => $e->getCode() ?? 1,
'file' => $e->getFile(), //获取出错误的文件
'line' => $e->getLine(), //获取错误在哪一行
'message' => $e->getMessage() ?? "error!",
'data' => []
]);
}
}
再次运行结果就是json:
{
"code": 0,
"file": "/home/vagrant/www/admin/app/Http/Admin/User/UserController.php",
"line": 17,
"message": "出bug啦",
"data": []
}
可以再验证一下数据库方面的,比如查询的字段在表里根本没有,看看能不能返回json:
控制器代码:
<?php
namespace App\Http\Admin\User;
use App\Http\Admin\Controller;
class UserController extends Controller
{
public function test()
{
//lmobile字段在表中没有
UserAdmin::find(2, ['id', 'lmobile']);
}
}
结果如下:
{
"code": "42S22",
"file": "/home/vagrant/www/admin/vendor/laravel/framework/src/Illuminate/Database/Connection.php",
"line": 712,
"message": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'lmobile' in 'field list' (SQL: select `id`, `lmobile` from `user_admin` where `user_admin`.`id` = 2 limit 1)",
"data": []
}
同样的也能正常返回json格式。
如果你不想改动app\Exceptions\Handler.php还有一种方法:通过设置请求头的accept:
如果前端同学加了accept头为application/json
如果你当心前端同学忘记加这个,我们也可以在框架路由配置那边加:
<?php
use App\Http\Api\User\AgreementController;
use App\Http\Api\User\UserController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
if (!request()->headers->get('accept')) {
request()->headers->set('accept', 'application/json');
}
Route::any("/user/test", [UserController::class, "test"]);
同样可以达到效果,当然你也可以采用中间件的方式,新建一个中间件,在handle方法里面第一句就写上$request->headers->set('accept', 'application/json');
然后把该中间件放到app\Http\Kernel.php的$middleware全局路由数组里面就可。
本作品采用《CC 协议》,转载必须注明作者和本文链接
请求的时候添加上
Accept: application/json
也可以