Laravel 强制 api 路由组返回 JSON

Laravel 的默认错误处理器通过 Illuminate\Http\RequestexpectsJson() 方法来决定是否将错误信息渲染成 JSON 格式输出。这要求将请求头的 Accept 字段设置为 application/json。本文提供一种方法,在尽可能减少代码的情况下,强制让 api 路由组中的所有错误响应变成 JSON 格式,而不依赖于请求的 Accept 头部。

第一步,新建 ExpectsJson 中间件,内容如下:

PHP<?php

namespace App\Http\Middleware;

use Illuminate\Http\Request;

class ExpectsJson
{
    /**
     * Handle the incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  callable  $next
     * @return \Illuminate\Http\Response
     */
    public function handle(Request $request, $next)
    {
        // force $request->expectsJson() return true
        ((function () {
            $this->acceptableContentTypes = ['application/json'];
        })->bindTo($request, Request::class))();

        return $next($request);
    }
}

第二步,启用该中间件。修改 app\Http\Kernel.php 文件:

PHP/**
 * The application's route middleware groups.
 *
 * @var array
 */
protected $middlewareGroups = [
	... ...
    'api' => [
        ... ...
        \App\Http\Middleware\ExpectsJson::class,    // 添加中间件到 api 组
    ],
];

... ...

/**
 * The priority-sorted list of middleware.
 *
 * Forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    \App\Http\Middleware\ExpectsJson::class,    // 调整中间件顺序在 AuthenticatesRequests 之前
    ... ...
    \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
    ... ...
];

该方法的原理就是:利用闭包修改 Illuminate\Http\Request 的保护成员,使得 expectsJson() 方法返回 true。