- 在多个控制器中引入 ApiMessage,替换原有的 ApiResponse 错误处理逻辑,确保错误信息的一致性与可读性。 - 更新错误返回信息,使用更具语义的键值,提升 API 的可维护性与用户体验。 - 适配相关控制器的请求参数,确保在处理错误时能够正确返回相应的错误信息。
141 lines
3.8 KiB
PHP
141 lines
3.8 KiB
PHP
<?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;
|
||
}
|
||
}
|