refactor: 使用 ApiMessage 统一错误响应格式

- 在多个控制器中引入 ApiMessage,替换原有的 ApiResponse 错误处理逻辑,确保错误信息的一致性与可读性。
- 更新错误返回信息,使用更具语义的键值,提升 API 的可维护性与用户体验。
- 适配相关控制器的请求参数,确保在处理错误时能够正确返回相应的错误信息。
This commit is contained in:
2026-06-01 14:23:48 +08:00
parent e547e2b4a6
commit e6cf94af46
59 changed files with 518 additions and 230 deletions

140
app/Support/ApiMessage.php Normal file
View File

@@ -0,0 +1,140 @@
<?php
declare(strict_types=1);
namespace App\Support;
use App\Lottery\ErrorCode;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Lang;
/**
* API 响应文案zh / en / ne msg 字段与 RuntimeException reason 翻译。
*/
final class ApiMessage
{
/** @var list<string> */
private const LOOKUP_PREFIXES = ['api.reasons.', 'api.', 'admin.', 'jackpot.', 'wallet.'];
public static function locale(?Request $request = null): string
{
$request ??= request();
if ($request instanceof Request && $request->attributes->has('lottery_locale')) {
return (string) $request->attributes->get('lottery_locale');
}
return LotteryLocale::resolve($request instanceof Request ? $request : null);
}
/**
* @param array<string, string|int|float> $replace
*/
public static function get(?Request $request, string $key, array $replace = []): string
{
$locale = self::locale($request);
$fallback = (string) config('lottery.locales.fallback', 'en');
foreach ([$locale, $fallback] as $tryLocale) {
foreach (self::candidateKeys($key) as $fullKey) {
$msg = trans($fullKey, $replace, $tryLocale);
if ($msg !== $fullKey && $msg !== '') {
return $msg;
}
}
}
return $key;
}
/**
* RuntimeException / 业务 reason 机器码 用户可见文案。
*
* @param array<string, string|int|float> $replace
*/
public static function reason(?Request $request, string $reasonKey, array $replace = []): string
{
$reasonKey = trim($reasonKey);
if ($reasonKey === '') {
return self::get($request, 'client_error', $replace);
}
$translated = self::get($request, $reasonKey, $replace);
if ($translated !== $reasonKey) {
return $translated;
}
return self::get($request, 'client_error', $replace);
}
public static function successMessage(?Request $request = null): string
{
return self::get($request, 'success.ok');
}
/**
* @param array<string, string|int|float> $replace
*/
public static function errorResponse(
?Request $request,
string $messageKey,
int $code,
mixed $data = null,
int $httpStatus = 400,
array $replace = [],
): JsonResponse {
return ApiResponse::error(
self::get($request, $messageKey, $replace),
$code,
$data,
$httpStatus,
);
}
public static function runtimeErrorResponse(
?Request $request,
\RuntimeException $exception,
int $code = 0,
int $httpStatus = 409,
): JsonResponse {
$reason = trim($exception->getMessage());
$resolvedCode = $code !== 0 ? $code : ErrorCode::ClientHttpError->value;
return ApiResponse::error(
self::reason($request, $reason),
$resolvedCode,
['reason' => $reason],
$httpStatus,
);
}
/**
* @return list<string>
*/
private static function candidateKeys(string $key): array
{
$key = trim($key);
if ($key === '') {
return ['api.client_error'];
}
if (str_contains($key, '.')) {
return array_values(array_unique([
$key,
'api.'.$key,
'admin.'.$key,
'jackpot.'.$key,
'wallet.'.$key,
'api.reasons.'.$key,
]));
}
$keys = [];
foreach (self::LOOKUP_PREFIXES as $prefix) {
$keys[] = $prefix.$key;
}
return $keys;
}
}