Laravel 响应:永远返回 JSON 响应 0 个改进

当你在编写完全为 API 服务的 Laravel 应用时,你希望所有响应都是 JSON 格式的,而不是例如说授权错误会重定向到 /home 或 /login,最终重定向会变成 InvalidArgumentException: Route [login] is not defined. 的视图。

下面这个简单的方案,可以让你的 Laravel 应用优先响应为 JSON 格式。

第一步、编写 BaseRequest

首先我们需要构建一个 BaseRequest 来重写 Illuminate\Http\Request ,修改为默认优先使用 JSON 响应:

app/Http/Requests/BaseRequest.php

<?php
namespace App\Http\Requests;

use Illuminate\Http\Request;
class BaseRequest extends Request
{
    public function expectsJson()
    {
        return true;
    }
    public function wantsJson()
    {
        return true;
    }
}

第二步、替换 BaseRequest

public/index.php 文件中,将 \Illumiate\Http\Request 替换为我们的 BaseRequest,如下:

$response = $kernel->handle(
    $request = \App\Http\Requests\BaseRequest::capture()
);

搞定!

现在所有的响应都是 application/json ,包括错误和异常。

本文为 Wiki 文章,邀您参与纠错、纰漏和优化
讨论数量: 31

我來貢獻一下我自己的做法

新增 middleware

namespace App\Http\Middleware;

use Closure;

class ForceJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $request->headers->set('accept', 'application/json');

        return $next($request);
    }
}

Kernel.php 加入

'force-json' => \App\Http\Middleware\ForceJson::class,

routes/api.php

Route::group(['middleware' => ['force-json', 'auth:api']], function () {
    // put your router
});

打完收功

這樣的做法可以任意指定 router 的行為
還可以不用更動到 Laravel 原生的程式碼

2年前 评论
elesos 1年前
ouyangessen 3个月前
recca0120 (作者) 2个月前
Illusion_ 1个月前
PowerFul 1天前

黑科技

2年前 评论

黑科技

2年前 评论

66666, 又学到了

2年前 评论

果然是骚操作

2年前 评论

黑科技,学到了

2年前 评论
GhostCoder

666666666

2年前 评论
GalaxyNo_1

:gem: 黑科技

2年前 评论
sushengbuhuo

666

2年前 评论

喜欢黑科技,666

2年前 评论

我來貢獻一下我自己的做法

新增 middleware

namespace App\Http\Middleware;

use Closure;

class ForceJson
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $request->headers->set('accept', 'application/json');

        return $next($request);
    }
}

Kernel.php 加入

'force-json' => \App\Http\Middleware\ForceJson::class,

routes/api.php

Route::group(['middleware' => ['force-json', 'auth:api']], function () {
    // put your router
});

打完收功

這樣的做法可以任意指定 router 的行為
還可以不用更動到 Laravel 原生的程式碼

2年前 评论
elesos 1年前
ouyangessen 3个月前
recca0120 (作者) 2个月前
Illusion_ 1个月前
PowerFul 1天前
ThinkCsly

厉害

2年前 评论

牛逼啊,省的总是要在headers中加一个xhr....

2年前 评论

哈哈哈,为什么我想笑啊,哈哈哈哈

2年前 评论
wujunze

不错

2年前 评论
sureyee

这个在请求头中加入Accept:application/json就可以了吧

2年前 评论
GalaxyNo_1

牛叉

2年前 评论
Shuyi

如果这样,不如直接用Lumen。。。

2年前 评论
wanghan

@recca0120 我觉得你的方法更好

2年前 评论
黑将军

@recca0120 我也是用这种方法

2年前 评论

@recca0120 同样是九年义务教育,niTM 怎么这么优秀

2年前 评论

@recca0120 其实~你的做法好,但这个 accept 的设置应该在前端或请求段,不应该服务器自己手动设置;

2年前 评论

@Moting 這個是單純的思路,可以快速的解決這個需求,但如你所說的不該我們設置,所以應該再多一行判斷式才對,判斷 request header accept 有無值,有值就不做任何動作,空值就補 header ,這樣就把控制權還給 client 了

2年前 评论

好骚的操作啊,可是为啥呢,大神能不能讲讲原因啊

2年前 评论

楼主这个太暴力啦,假设项目同时提供web和api两种服务,更通用的做法应该根据不同的路由前缀进行不同的返回。

2年前 评论

哈哈哈哈

1年前 评论

2020-06-13 更新: 虽然写在 api.php 路由文件中,但是污染了所有路由请求(web.php 路由也受到影响),请谨慎使用,还是推荐写在中间件中吧,可控性高一些

根据 @recca0120 的中间件方法,想到一个更简单的方法,需要返回 Json 数据的基本都是接口,所以在路由文件 api.php 最上面添加一行代码(当然也可以写在 web.php 中)

request()->headers->set('accept', 'application/json');

这样连中间件都不用写了,缺点是不能单独控制每个接口(既然都写到接口路由里,应该不需要返回 json 以外的数据吧),如果没有命中接口路由,返回 404 页不是 json 数据(因为跟本没进路由文件 api.php 当然就无效了),但是如果命中路由后返回的 404 就是正常的 json 数据了

1年前 评论
宋高峰 6个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!