Handler.php中的渲染函数在Laravel 8中无效

10

当发生ModelNotFoundException时,我希望返回JSON响应而不是默认的404错误页面。为了实现这一点,我在app\Exceptions\Handler.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中声明一个空的render函数,Laravel也会在ModelNotFoundException上显示一个空白页面。

我该如何修复这个问题,以便能够返回JSON / 执行重写的render函数内部的逻辑?

4个回答

21
在Laravel 8x中,您需要在register()方法中Rendering Exceptions
use App\Exceptions\CustomException;

/**
 * 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 Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

public function register()
{
    $this->renderable(function (NotFoundHttpException $e, $request) {
        return response()->json(...);
    });
}

默认情况下,Laravel异常处理程序将为您将异常转换为HTTP响应。然而,您可以自由地为给定类型的异常注册自定义渲染闭包。您可以通过异常处理程序的renderable方法来实现这一点。 Laravel将通过检查闭包的类型提示来推断Closure呈现的异常类型:

有关错误异常的更多信息


1
很高兴能帮助你 :) - Dilip Hirapara
3
为什么在ModelNotFoundException的处理程序中必须使用NotFoundHttpException异常?我遇到了一个问题,即NotFoundHttpException也会对404错误抛出,但我想针对这些异常抛出不同的错误。 - Lukerayner

8
这段代码在我的环境下无法工作(在Laravel 8.74.0中):
$this->renderable(function (ModelNotFoundException$e, $request) {
    return response()->json(...);
});

不知道为什么,但ModelNotFoundException被直接转发到NotFoundHttpException(这是Symfony组件的一部分),该组件被Laravel使用并最终触发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


1
这必须被接受为 Laravel 8+ 的答案。 - Alexey Shatrov
别忘了打电话: 使用Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 使用Illuminate\Database\Eloquent\ModelNotFoundException; - undefined

2

这是我的处理程序文件:

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语句。

这个不起作用。我也想在我的API路径中使用它,所以我保留了第一个if,但不幸的是它还是显示空白页面。 - user9158270

0
请注意,默认情况下,仅当您发送带有头参数 Accept: application/json 的请求时,Laravel 才会发出异常的 JSON 表示!对于所有其他请求,Laravel 发送正常的 HTML 渲染输出。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接