当ModelNotFoundException发生时,我希望返回JSON响应,而不是默认的404错误页面。为此,我在appExceptionsHandler.php
:中编写了以下代码
public function render($request, Exception $exception)
{
if ($exception instanceof ModelNotFoundException) {
return response()->json([
'error' => 'Resource not found'
], 404);
}
return parent::render($request, $exception);
}
但是它不起作用。当ModelNotFoundException发生时,Laravel只显示一个空白页面。我发现,即使在Handler.php
中声明一个空的渲染函数,Laravel也会在ModelNotFoundException上显示一个空白页面。
如何修复此问题,使其能够返回JSON/执行overriden呈现函数内的逻辑?
在Laravel 8x中,您需要在register()
方法中使用Rendering Exceptions
use AppExceptionsCustomException;
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->renderable(function (CustomException $e, $request) {
return response()->view('errors.custom', [], 500);
});
}
对于ModelNotFoundException
,您可以按以下方式进行操作。
use SymfonyComponentHttpKernelExceptionNotFoundHttpException;
public function register()
{
$this->renderable(function (NotFoundHttpException $e, $request) {
return response()->json(...);
});
}
默认情况下,Laravel异常处理程序会将异常转换为HTTP响应。但是,您可以为给定类型的异常注册自定义呈现闭包。您可以通过异常处理程序的renderable
方法来实现这一点。Laravel将通过检查闭包的类型提示来推断闭包呈现的异常类型:
有关错误异常的更多信息
此代码不适用于我(在Laravel 8.74.0中(:
$this->renderable(function (ModelNotFoundException$e, $request) {
return response()->json(...);
});
不知道为什么,但ModelNotFoundException
被直接转发到Laravel使用的NotFoundHttpException
(它是Symfony组件的一部分(,并最终触发404 HTTP响应。我的解决方法是检查异常的getPrevious()
方法:
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->is('api/*')) {
if ($e->getPrevious() instanceof ModelNotFoundException) {
return response()->json([
'status' => 204,
'message' => 'Data not found'
], 200);
}
return response()->json([
'status' => 404,
'message' => 'Target not found'
], 404);
}
});
然后我们就会知道这个异常来自ModelNotFoundException
,并用NotFoundHttpException
返回不同的响应。
编辑
这就是ModelNotFoundException
作为NotFoundHttpException
抛出的原因
这是我的处理程序文件:
use Throwable;
public function render($request, Throwable $exception)
{
if( $request->is('api/*')){
if ($exception instanceof ModelNotFoundException) {
$model = strtolower(class_basename($exception->getModel()));
return response()->json([
'error' => 'Model not found'
], 404);
}
if ($exception instanceof NotFoundHttpException) {
return response()->json([
'error' => 'Resource not found'
], 404);
}
}
}
这只适用于API路由中的所有请求。如果您想捕获所有请求,请删除第一个If.
请注意,默认情况下,Laravel仅在发送带有标头参数Accept: application/json
的请求时才会发出异常的JSON表示!对于所有其他请求,Laravel发送正常的HTML渲染输出。