1. 在 /config/app 设置时区

'timezone' => 'Asia/Shanghai',

2. 添加 Accept MidlleWare,解决验证参数返回json问题

  1. 创建 MiddleWare
php artisan make:middleware AcceptJsonHeader
  1. 添加 AcceptHeader 为 application/json
<?php

namespace AppHttpMiddleware;

use Closure;
use IlluminateHttpRequest;
use SymfonyComponentHttpFoundationResponse;

class AcceptJsonHeader
{
    /**
     * Handle an incoming request.
     *
     * @param  Closure(IlluminateHttpRequest): (SymfonyComponentHttpFoundationResponse)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        // 设置 为 application/json
        $request->headers->set("Accept", "application/json");
        return $next($request);
    }
}

  1. /bootstrap/app.php 配置 middleware
<?php

use IlluminateFoundationApplication;
use IlluminateFoundationConfigurationExceptions;
use IlluminateFoundationConfigurationMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        api: __DIR__.'/../routes/api.php',
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        // 为 api 配置 midlleware
        $middleware->appendToGroup('api', [
            AppHttpMiddlewareAcceptJsonHeader::class
        ]);
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        //
    })->create();

3. 国际化

  1. 创建语言文件
php artisan lang:publish
  1. 配置语言
  • .env 中的 APP_LOCALE
  • app()->setLocale($locale)
  1. 添加语言文件 zh_CN
  2. 使用 __ 函数显示翻译字符串

4. 响应

  1. 编写统一响应
<?php

namespace AppHttpResponse;

/**
 * API 响应状态码枚举
 *
 * 遵循阿里巴巴 Java 开发手册错误码规范
 * - 00000: 成功
 * - A 系列: 用户端错误 (Client Error)
 * - B 系列: 系统执行错误 (System Error)
 * - C 系列: 第三方服务错误 (Third-party Error)
 */
enum ApiResponseEnum: string
{
    // ==================== 成功 ====================
    case SUCCESS = '00000';

    // ==================== A 系列:用户端错误 ====================
    case USER_ERROR = 'A0001';              // 用户端错误
    case INVALID_PARAMS = 'A0400';          // 请求参数错误
    case VALIDATION_FAILED = 'A0402';       // 数据校验失败
    case UNAUTHORIZED = 'A0300';            // 用户未登录
    case FORBIDDEN = 'A0301';               // 访问权限不足
    case NOT_FOUND = 'A0404';               // 请求资源不存在
    case METHOD_NOT_ALLOWED = 'A0405';      // 请求方法不允许
    case TOO_MANY_REQUESTS = 'A0429';       // 请求过于频繁

    // ==================== B 系列:系统执行错误 ====================
    case SYSTEM_ERROR = 'B0001';            // 系统执行错误
    case SYSTEM_TIMEOUT = 'B0100';          // 系统执行超时
    case DB_ERROR = 'B0300';                // 数据库执行异常
    case DISK_FULL = 'B0101';               // 系统磁盘空间不足

    // ==================== C 系列:第三方服务错误 ====================
    case THIRD_PARTY_ERROR = 'C0001';       // 第三方服务错误
    case THIRD_PARTY_TIMEOUT = 'C0100';     // 第三方服务超时

    /**
     * 获取状态码对应的翻译键
     */
    public function translationKey(): string
    {
        return match($this) {
            self::SUCCESS => 'response.success',
            self::USER_ERROR => 'response.user_error',
            self::INVALID_PARAMS => 'response.invalid_params',
            self::VALIDATION_FAILED => 'response.validation_failed',
            self::UNAUTHORIZED => 'response.unauthorized',
            self::FORBIDDEN => 'response.forbidden',
            self::NOT_FOUND => 'response.not_found',
            self::METHOD_NOT_ALLOWED => 'response.method_not_allowed',
            self::TOO_MANY_REQUESTS => 'response.too_many_requests',
            self::SYSTEM_ERROR => 'response.system_error',
            self::SYSTEM_TIMEOUT => 'response.system_timeout',
            self::DB_ERROR => 'response.db_error',
            self::DISK_FULL => 'response.disk_full',
            self::THIRD_PARTY_ERROR => 'response.third_party_error',
            self::THIRD_PARTY_TIMEOUT => 'response.third_party_timeout',
            default => 'response.unknown_error',
        };
    }

    /**
     * 获取状态码对应的默认消息(支持国际化)
     */
    public function message(): string
    {
        return __($this->translationKey());
    }

    /**
     * 获取对应的 HTTP 状态码
     */
    public function httpStatus(): int
    {
        return match($this) {
            self::SUCCESS => 200,

            self::INVALID_PARAMS, self::VALIDATION_FAILED => 422,
            self::UNAUTHORIZED => 401,
            self::FORBIDDEN => 403,
            self::NOT_FOUND => 404,
            self::METHOD_NOT_ALLOWED => 405,
            self::TOO_MANY_REQUESTS => 429,

            self::SYSTEM_ERROR, self::SYSTEM_TIMEOUT,
            self::DB_ERROR, self::DISK_FULL => 500,

            self::THIRD_PARTY_ERROR, self::THIRD_PARTY_TIMEOUT => 503,

            default => 500,
        };
    }
}
<?php

namespace AppHttpResponse;

use IlluminateHttpJsonResponse;

/**
 * 统一 API 响应类
 *
 * 响应格式:
 * {
 *     "code": "00000",
 *     "message": "操作成功",
 *     "data": {...}
 * }
 */
class ApiResponse
{
    /**
     * 成功响应
     *
     * @param mixed $data 响应数据
     * @param string|null $message 自定义消息
     * @return JsonResponse
     */
    public static function success(mixed $data = null, ?string $message = null): JsonResponse
    {
        return self::response(
            ApiResponseEnum::SUCCESS,
            $message ?? ApiResponseEnum::SUCCESS->message(),
            $data
        );
    }

    /**
     * 失败响应
     *
     * @param ApiResponseEnum $code 错误码枚举
     * @param string|null $message 自定义错误消息
     * @param mixed $data 附加数据
     * @return JsonResponse
     */
    public static function fail(
        ApiResponseEnum $code = ApiResponseEnum::USER_ERROR,
        ?string $message = null,
        mixed $data = null
    ): JsonResponse {
        return self::response(
            $code,
            $message ?? $code->message(),
            $data,
            $code->httpStatus()
        );
    }

    /**
     * 参数验证失败响应
     *
     * @param string|array $errors 验证错误信息
     * @param mixed $data 附加数据
     * @return JsonResponse
     */
    public static function validationFailed(string|array $errors, mixed $data = null): JsonResponse
    {
        $message = is_array($errors) ? implode('; ', $errors) : $errors;

        return self::response(
            ApiResponseEnum::VALIDATION_FAILED,
            $message,
            $data,
            ApiResponseEnum::VALIDATION_FAILED->httpStatus()
        );
    }

    /**
     * 未授权响应 (401)
     *
     * @param string|null $message 自定义消息
     * @return JsonResponse
     */
    public static function unauthorized(?string $message = null): JsonResponse
    {
        return self::fail(ApiResponseEnum::UNAUTHORIZED, $message);
    }

    /**
     * 禁止访问响应 (403)
     *
     * @param string|null $message 自定义消息
     * @return JsonResponse
     */
    public static function forbidden(?string $message = null): JsonResponse
    {
        return self::fail(ApiResponseEnum::FORBIDDEN, $message);
    }

    /**
     * 资源不存在响应 (404)
     *
     * @param string|null $message 自定义消息
     * @return JsonResponse
     */
    public static function notFound(?string $message = null): JsonResponse
    {
        return self::fail(ApiResponseEnum::NOT_FOUND, $message);
    }

    /**
     * 系统错误响应 (500)
     *
     * @param string|null $message 自定义消息
     * @param mixed $data 附加数据
     * @return JsonResponse
     */
    public static function systemError(?string $message = null, mixed $data = null): JsonResponse
    {
        return self::fail(ApiResponseEnum::SYSTEM_ERROR, $message, $data);
    }

    /**
     * 第三方服务错误响应 (503)
     *
     * @param string|null $message 自定义消息
     * @return JsonResponse
     */
    public static function thirdPartyError(?string $message = null): JsonResponse
    {
        return self::fail(ApiResponseEnum::THIRD_PARTY_ERROR, $message);
    }

    /**
     * 构建统一响应
     *
     * @param ApiResponseEnum $code 业务状态码
     * @param string $message 响应消息
     * @param mixed $data 响应数据
     * @param int|null $httpStatus HTTP 状态码
     * @return JsonResponse
     */
    private static function response(
        ApiResponseEnum $code,
        string $message,
        mixed $data = null,
        ?int $httpStatus = null
    ): JsonResponse {
        $response = [
            'code' => $code->value,
            'message' => $message,
            'data' => $data,
        ];

        return response()->json(
            $response,
            $httpStatus ?? $code->httpStatus()
        );
    }
}
  1. 配置错误处理
<?php

use IlluminateFoundationApplication;
use IlluminateFoundationConfigurationExceptions;
use IlluminateFoundationConfigurationMiddleware;
use IlluminateValidationValidationException;
use IlluminateDatabaseEloquentModelNotFoundException;
use IlluminateAuthAuthenticationException;
use IlluminateAuthAccessAuthorizationException;
use SymfonyComponentHttpKernelExceptionNotFoundHttpException;
use SymfonyComponentHttpKernelExceptionMethodNotAllowedHttpException;
use SymfonyComponentHttpKernelExceptionTooManyRequestsHttpException;
use AppHttpResponseApiResponse;
use AppHttpMiddlewareSetLocale;
use IlluminateHttpRequest;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        api: __DIR__.'/../routes/api.php',
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware): void {
        // 全局中间件:自动设置语言
        $middleware->append(SetLocale::class);
    })
    ->withExceptions(function (Exceptions $exceptions): void {
        // 422 - 验证失败
        $exceptions->render(function (ValidationException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::validationFailed($e->validator->errors()->all());
            }
        });

        // 404 - 模型未找到
        $exceptions->render(function (ModelNotFoundException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::notFound(__('response.resource_not_found'));
            }
        });

        // 404 - 路由未找到
        $exceptions->render(function (NotFoundHttpException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::notFound(__('response.route_not_found'));
            }
        });

        // 405 - 请求方法不允许
        $exceptions->render(function (MethodNotAllowedHttpException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::fail(
                    AppHttpResponseApiResponseEnum::METHOD_NOT_ALLOWED
                );
            }
        });

        // 401 - 未认证
        $exceptions->render(function (AuthenticationException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::unauthorized();
            }
        });

        // 403 - 未授权
        $exceptions->render(function (AuthorizationException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::forbidden();
            }
        });

        // 429 - 请求过于频繁
        $exceptions->render(function (TooManyRequestsHttpException $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                return ApiResponse::fail(
                    AppHttpResponseApiResponseEnum::TOO_MANY_REQUESTS
                );
            }
        });

        // 500 - 系统错误(生产环境不暴露详细错误信息)
        $exceptions->render(function (Throwable $e, Request $request) {
            if ($request->expectsJson() || $request->is('api/*')) {
                $message = app()->environment('local', 'testing')
                    ? $e->getMessage()
                    : null;

                return ApiResponse::systemError($message);
            }
        });
    })->create();
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com