'Bad request.', 401 => 'Authentication required.', 403 => 'Forbidden.', 404 => 'Resource not found.', 405 => 'Method not allowed.', 409 => 'Conflict.', 419 => 'Page expired.', 422 => 'Your request is not valid.', 429 => 'Too many requests.', 500 => 'Server error.', 503 => 'Service unavailable.', ]; public static function titleFor(int $status): string { return self::TITLES[$status] ?? ( $status >= 500 ? self::TITLES[500] : self::TITLES[400] ); } /** * @param string $slug 问题类型标识,进 type 字段 * @param array $extra 扩展成员,如 ['errors' => [...]] */ public static function response( Request $request, int $status, string $slug, ?string $title = null, ?string $detail = null, array $extra = [] ): JsonResponse { $body = array_filter([ // 刻意用 URN 而不是 url():绝对地址由 APP_URL 拼出, // 反向代理下容易拼错,而且目前没有文档页可供解引用。 'type' => "urn:problem:{$slug}", 'title' => $title ?? self::titleFor($status), 'status' => $status, 'detail' => $detail, 'instance' => $request->getRequestUri(), ], fn ($v) => $v !== null && $v !== '') + $extra; return response()->json( $body, $status, ['Content-Type' => 'application/problem+json'], JSON_UNESCAPED_UNICODE ); } }