Laravel API 响应标准化:提高可读性和可用性

admin 2024-01-03 486 阅读 0评论

在使用 Laravel 构建 API 时,保持一致的响应格式对于清晰度和易用性至关重要。无论是成功响应还是错误响应,以标准化方式呈现数据都可以改善开发人员体验。

在本指南中,我们将探索如何在 Laravel 中使用自定义中间件来实现一致的响应格式。

第 1 步:创建自定义中间件

我们需要创建一个自定义中间件来处理所有 API 响应。我们可以使用 Artisan 命令来创建中间件:

php artisan make:middleware ApiResponseMiddleware

该命令将在 app/Http/Middleware 目录中生成一个名为 ApiResponseMiddleware 的中间件文件。

第 2 步:自定义中间件

我们需要自定义中间件来格式化 API 响应。

打开新创建的中间件文件 ApiResponseMiddleware.php,并更新 handle() 方法如下:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Throwable;

class ApiResponseMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param Request $request
     * @param Closure(Request): (Response|RedirectResponse) $next
     * @return JsonResponse
     * @throws Throwable
     */
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        // 检查请求是否需要 JSON
        if (!$request->wantsJson() && !$request->is('api/*')) {
            // 强制 API 请求为 JSON 响应
            return $next($request);
        }

        // 设置请求的 Accept 头为 application/json
        $request->headers->set('Accept''application/json');

        // 如果响应是 JsonResponse,则格式化它
        if ($response instanceof JsonResponse) {
            $data = $response->getData(true);

            // 创建标准化响应结构
            $formattedResponse = [
                'success' => array_key_exists('success'$data) ? $data['success'] : $response->status() == 200,
                'statusCode' => array_key_exists('statusCode'$data) ? $data['statusCode'] : $response->status(),
                'statusDescription' => array_key_exists('statusDescription'$data) ? $data['statusDescription'] : ($response->status() == 200 ? 'Successful' : ''),
                'data' => array_key_exists('data'$data) ? $data['data'] : ($response->status() == 200 ? $data : null),
            ];

            // 返回格式化的 JSON 响应
            return response()->json($formattedResponse$response->status());
        }

        // 原样返回响应
        return $next($request);
    }
}

该中间件检查请求是否需要 JSON。如果不需要,则将请求转发到下一个中间件。如果请求需要 JSON,则中间件将设置请求的 Accept 头为 application/json。这将确保响应以正确的格式发送。

然后,中间件检查响应是否是 JsonResponse 的实例。如果是,则中间件将解码响应内容,创建标准化响应结构,并返回格式化的 JSON 响应。对于非 JsonResponse 类型,中间件按原样返回响应。

第3步:注册中间件

我们需要将 ApiResponseMiddleware 注册到 app/Http/Kernel.php 文件中的 $middlewareGroups 数组中。我们可以将其添加到 web 和 api 中间件组中,以便全局应用它:

protected $middlewareGroups = [
    'web' => [
        // 其他中间件...
    ],
    'api' => [
        // 其他中间件...
        \App\Http\Middleware\ApiResponseMiddleware::class,
    ],
];

通过将中间件包含在 api 组中,它将应用于所有 API 路由。

第 4 步:确保控制器响应一致

为了充分利用中间件,请确保您的控制器以一致的格式返回响应。例如,当返回成功的响应时,其结构应如下所示:

return response()->json([
    'success' => true,
    'statusCode' => 200,
    'statusDescription' => 'Successful',
    'data' => $yourData,
]);

第 5 步:(可选)使用 JWT 令牌时防止返回 HTML 页面

为了防止在 JWT 令牌无效时返回 HTML 页面并返回 JSON 响应,您可以自定义 Laravel 的异常处理程序。Laravel 的默认异常处理程序在 App\Exceptions\Handler 类中提供了一个可以重写的 render() 方法。

以下示例说明了如何修改异常处理程序以返回无效 JWT 令牌的 JSON 响应:

1、打开 App\Exceptions\Handler 类。

2、更新 render() 方法如下:

<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Throwable;
use Illuminate\Auth\AuthenticationException;


class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param \Throwable $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param Request $request
     * @param Throwable $e
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $e)
    {
        // 检查异常是否是 AuthenticationException 的实例(JWT 身份验证)
        if ($e instanceof AuthenticationException) {
            return response()->json([
                'success' => false,
                'statusCode' => 401,
                'statusDescription' => 'Unauthorized: Invalid JWT Token',
                'data' => null,
            ], 401);
        }

        // 您可以根据需要添加多个异常

        if ($request->wantsJson() || $this->isApiRequest($request)) {
            return $this->formatApiResponse($e);
        }

        return parent::render($request$e);
    }


    protected function isApiRequest(Request $request): bool
    {
        // 确保您的 API 以 api 开头,或者您可以根据需要更新
        return Str::startsWith($request->path(), 'api/') || $request->expectsJson();
    }

    protected function formatApiResponse(Throwable $exception): JsonResponse
    {
        return response()->json([
            'success' => false,
            'statusCode' => $this->getStatusCode($exception),
            'statusDescription' => $exception->getMessage(),
            'data' => null,
        ], $this->getStatusCode($exception));
    }

    protected function getStatusCode(Throwable $exception)
    {
        return method_exists($exception'getStatusCode') ? $exception->getStatusCode() : 500;
    }
}

按照上述步骤,您可以在 Laravel 中实现一个自定义中间件,以一致地格式化 API 响应。这种方法可以提高 API 的可读性和可用性,使开发人员更容易使用和理解数据。您可以根据自己的需求调整中间件,以满足特定的 API 要求。例如,您可以添加或删除响应字段,或更改响应结构。

喜欢就支持以下吧
点赞 0

发表评论

快捷回复: 表情:
aoman baiyan bishi bizui cahan ciya dabing daku deyi doge fadai fanu fendou ganga guzhang haixiu hanxiao zuohengheng zhuakuang zhouma zhemo zhayanjian zaijian yun youhengheng yiwen yinxian xu xieyanxiao xiaoku xiaojiujie xia wunai wozuimei weixiao weiqu tuosai tu touxiao tiaopi shui se saorao qiudale qinqin qiaoda piezui penxue nanguo liulei liuhan lenghan leiben kun kuaikule ku koubi kelian keai jingya jingxi jingkong jie huaixiao haqian aini OK qiang quantou shengli woshou gouyin baoquan aixin bangbangtang xiaoyanger xigua hexie pijiu lanqiu juhua hecai haobang caidao baojin chi dan kulou shuai shouqiang yangtuo youling
提交
评论列表 (有 0 条评论, 486人围观)

最近发表

热门文章

最新留言

热门推荐

标签列表