框架如何统一api返回的json格式及状态码算是最佳实现

在开发 api 的时候,框架如何统一api返回的json格式及状态码算是最佳实现,有在控制器做的然后做继承,有 provider 下创建服务做的 function boot Response::macro (‘wrap’) ,也有Exceptions下抛异常的,看了实战架构api服务器教程的处理,也没有做到格式状态码的统一处理。 也有用扩展包的。五花八门,很想知道哪一种方式是最佳实现,如果用扩展包,用哪个比较好

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 12

这个真没有,每个公司有每个公司都规定。

如果非要追求个标准,参考 github v3api 接口文档。

1年前 评论
wangyou (楼主) 1年前

错误 我是都 throw 然后去 App\Exceptions\Handler 统一处理 因为是restful,正确的就直接return一个数组了,正确的也可以统一调用一个函数,有特殊情况,单独处理

1年前 评论

laravel 可以自定义宏来统一返回接口,在AppServiceProvider,下面是我的,你可以自行改动

    public function boot()
    {
        Response::macro('success', function($data, string $message, string $api = '', array $headers = []) {
            return Response::json(headers: $headers, data: [
                'api'     => $api ?: request()->route()->getName() ?: 'api.success.response',
                'message' => $message,
                'data'    => $data,
                'ret'     => 0,
                'v'       => '1.0',
            ]);
        });

        Response::macro('error', function(string $message, int $code = 1, int $status = 403, $data = null, string $api = '', array $headers = []) {
            return Response::json(headers: $headers, status: $status, data: [
                'api'     => $api ?: request()->route()->getName() ?: 'api.error.response',
                'message' => $message,
                'data'    => $data ?: [],
                'ret'     => $code ?: 1,
                'v'       => '1.0',
            ]);
        });
    }

ControllerMiddleware中这样调用

response()->success(['data' => []], '正确的接口');
response()->success(['data' => []], '带有头部信息的正确接口', headers: ['x-token' => 'xxxx']);
response()->error('错误的接口');
response()->error('带有数据的错误接口', data: ['data' => []]);
response()->error('指定编号的错误接口', 101);

对于抛出的异常,可以在Handler统一进行捕获后,抛出自定义宏,例如:

    public function render($request, Throwable $exception)
    {
        // 参数验证错误的异常,我们需要返回 400 的 http code 和一句错误信息
        if ($exception instanceof ValidationException) 
        {
            return response()->error(
                Arr::first(Arr::collapse($exception->errors())), 
                1, 
                400, 
                method_exists($exception->validator, 'attributes') ? call_user_func([$exception->validator, 'attributes']) : [], 
                'verify.task.api'
            );
        }
    }
1年前 评论

这个没办法完全统一,做法都不一样,如果是单一项目,统一化,如果还要对接其他项目,业务码可能还不一样,尽量规范化就行

1年前 评论

哪有什么最佳实现?难道不是适合自己的才是最好的吗?

1年前 评论
wangyou (楼主) 1年前

直接封装一个Response契约类,用服务容器绑定需要的Response类

1年前 评论

参考一个chatGpt的回答 在 Laravel 中实现统一的 API 返回格式和状态码可以采用多种方法,每种方法都有其优缺点,需要根据具体情况进行选择。

以下是常见的几种方法:

继承控制器基类并重写 sendResponse() 和 sendError() 方法。 这种方法适用于只有少量 API,且返回格式和状态码不会变化的情况。具体实现可以在控制器基类中封装通用的返回格式和状态码,子控制器只需要根据具体业务实现自己的方法即可。

使用全局中间件,重写响应格式。 这种方法适用于需要全局统一 API 返回格式和状态码的情况。具体实现可以在中间件中拦截所有 API 响应,重写响应格式,并返回统一的状态码。需要注意的是,这种方法可能会影响到其他响应,如 HTML 响应等。

使用异常处理器,抛出异常并统一处理。 这种方法适用于需要在多个控制器中使用同一种异常处理方式的情况。具体实现可以在异常处理器中捕获所有需要处理的异常,并返回统一的错误响应。需要注意的是,这种方法会增加代码的复杂度和维护成本。

使用第三方扩展包,如 spatie/laravel-response-serializer。 这种方法适用于需要快速、方便地实现 API 响应格式和状态码统一的情况。具体实现可以通过引入扩展包,使用其中提供的工具类和方法来实现统一处理。需要注意的是,使用第三方扩展包可能会增加项目的依赖和复杂度,需要谨慎选择。

综合考虑,使用全局中间件和使用第三方扩展包是比较常用和推荐的方法,具体选择取决于项目的实际需求和情况。对于使用扩展包的情况,可以选择一些比较常用和成熟的扩展包,如 spatie/laravel-response-serializer 或 dingo/api,它们提供了丰富的功能和灵活的配置,可以满足大部分项目的需求。

1年前 评论
Jianne

想起来之前写过一篇 教你更优雅地写 API 之「规范响应数据」,可以一起讨论下

1年前 评论

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