Laravel 404和500的API和网站中的不同响应(JSON和网页)?

Laravel 404和500的API和网站中的不同响应(JSON和网页)?,laravel,laravel-5.4,Laravel,Laravel 5.4,我想显示API和网站的不同响应。在api响应中,我想显示json响应,其中404和500表示主要用于路由的异常类型 如果一个用户试图请求一个路由,但没有找到路由,我想在json响应中为API显示一个响应,在Web页面中为网站显示一个响应 我知道并尝试将代码放入app/Exceptions/Handler.php public function render($request, Exception $exception) { if ($exception instanceof NotFou

我想显示API和网站的不同响应。在api响应中,我想显示json响应,其中404和500表示主要用于路由的异常类型

如果一个用户试图请求一个路由,但没有找到路由,我想在json响应中为API显示一个响应,在Web页面中为网站显示一个响应

我知道并尝试将代码放入
app/Exceptions/Handler.php

public function render($request, Exception $exception)
{
    if ($exception instanceof NotFoundHttpException) {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Not Found'], 404);
        }
        return response()->view('404', [], 404);
    }
    return parent::render($request, $exception);
}
public function render($request, Exception $exception)
{
    // Give detailed stacktrace error info if APP_DEBUG is true in the .env
    if ($request->wantsJson()) {
      // Return reasonable response if trying to, for instance, delete nonexistent resource id.
      if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
        return response()->json(['data' => 'Resource not found'], 404);
      }
      if ($_ENV['APP_DEBUG'] == 'false') {
        return response()->json(['error' => 'Unknown error'], 400);
      }
    }
    return parent::render($request, $exception);
}

但是失败了。有人能帮助我如何为错误页面设置不同的响应。

试试这个。

public function render($request, Exception $exception)
    {
        if ($request->ajax()) {
            return \Response::json([
                'success' => false,
                'message' => $exception->getMessage(),
            ], $exception->getCode());
        } else {
            return parent::render($request, $exception);
        }
    }

预期
JSON
是关于标题的,我不喜欢
API
错误的解决方案,您可以通过浏览器访问
API
。我的解决方案大多数情况下是通过
URL
路由进行过滤,因为它以
“api/…”
开头,可以像这样执行
$request->is('api/*')

如果您的路由不是带有
/api
前缀的路由,那么这将不起作用。更改逻辑以适合您自己的结构

public function render($request, Exception $exception)
{
    if ($exception instanceof NotFoundHttpException) {
        if ($request->is('api/*')) {
            return response()->json(['error' => 'Not Found'], 404);
        }
        return response()->view('404', [], 404);
    }
    return parent::render($request, $exception);
}

我使用的是Laravel5.5.28,并在
app/Exceptions/Handler.php

public function render($request, Exception $exception)
{
    if ($exception instanceof NotFoundHttpException) {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Not Found'], 404);
        }
        return response()->view('404', [], 404);
    }
    return parent::render($request, $exception);
}
public function render($request, Exception $exception)
{
    // Give detailed stacktrace error info if APP_DEBUG is true in the .env
    if ($request->wantsJson()) {
      // Return reasonable response if trying to, for instance, delete nonexistent resource id.
      if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
        return response()->json(['data' => 'Resource not found'], 404);
      }
      if ($_ENV['APP_DEBUG'] == 'false') {
        return response()->json(['error' => 'Unknown error'], 400);
      }
    }
    return parent::render($request, $exception);
}
这期望您的API调用将有一个带有键
Accept
和值
application/json
的头

然后,不存在的web路由返回预期的

很抱歉,找不到您要查找的页面

一个不存在的API资源返回一个JSON 404负载

找到了


您可以将其与查找
NotFoundHttpException
实例的答案结合起来,以捕获500。不过,我想最好使用堆栈跟踪。

无需再次为Laravel升级而忙碌。您只需要在routes/api.php中定义此方法


我只是想在上述答案的基础上添加一个替代方案,所有这些似乎都很有效

在遇到同样的问题并深入挖掘之后,我采取了一种稍微不同的方法:

  • 异常句柄调用父::呈现(…)。如果查看该函数,如果您的请求指示它
    wantsJson()
    [请参阅]

  • 现在,为了将所有响应(包括异常)转换为json,我使用了来自的Jsonify中间件思想,但将其应用于api MiddlewareGroup,该api默认分配给RouteServiceProvider::mapApiRoutes()

下面是一种实现方法(与上面的参考答案非常类似):

  • 创建文件
    app/Http/Middleware/Jsonify.php

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    
    class Jsonify
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            if ( $request->is('api/*') ) {
                $request->headers->set('Accept', 'application/json');
            }
            return $next($request);
        }
    }
    
  • 在同一内核文件中,将jsonify名称添加到api组:

    protected $middlewareGroups = [
    ...
      'api' => [
        'jsonify',
        'throttle:60,1',
        'bindings',            
      ],
    ...
    ];
    

  • 结果是,对于属于“api”组的任何请求,都会加载中间件。如果请求url以
    api/
    开头(我认为这有点多余),那么Jsonify中间件会添加头。这将告诉ExceptionHandler::render()我们需要json输出

    这对我很有用,还添加了
    使用Symfony\Component\HttpKernel\Exception\NotFoundHttpException谢谢“X-Requested-With”:“XMLHttpRequests”需要添加标题,否则laravel请求不会检测为ajex调用,这就是为什么返回页面。遗憾的是,这在大多数情况下都有效,但在某些情况下不起作用:如果您从策略或网关获得“未授权”,则您的中间件可能尚未加载。如果没有加载jsonify,您将获得非json输出,除非您相应地设置了头(接受Application/json)。因此,您可以使用这个答案,只是要注意不足……如果您要将其添加到
    api
    中间件组,则无需在请求URL中检查
    /api
    。路由服务提供商将
    api
    中间件组和
    /api
    前缀应用于
    api.php
    中列出的路由。使用GET方法可以很好地工作。但与其他方法(POST、PUT等)相同的url将返回405 methodNotLowed。我建议通过这种方式在api路由的末尾定义自定义回退路由()对于Laravel 8,请参见以下答案