[], 'type' => [], 'tmp_name' => [], 'size' => [], 'fileType' => []]; foreach ($laravelFiles as $file) { $files['name'][] = $file->getClientOriginalName(); $files['type'][] = $file->getClientMimeType(); $files['tmp_name'][] = $file->getPathname(); $files['size'][] = $file->getSize(); $files['fileType'][] = ''; } return $files; } // DebugQuery Helper public static function debugQueryLog(): array { $logs = DB::getQueryLog(); return collect($logs) ->skip(3) ->map(function ($log) { $query = $log['query']; foreach ($log['bindings'] as $binding) { $binding = is_numeric($binding) ? $binding : "'".addslashes($binding)."'"; $query = preg_replace('/\\?/', $binding, $query, 1); } // \n 제거 $query = str_replace(["\n", "\r"], ' ', $query)." (time: {$log['time']})"; return trim($query); })->toArray(); } // ApiResponse Helper public static function success( $data = null, string $message = '요청 성공', array $debug = [] ): JsonResponse { $response = [ 'success' => true, 'message' => $message, 'data' => $data, ]; if (! empty($debug)) { $response['query'] = $debug; } return response()->json($response); } public static function error( string $message = '요청 실패', int $code = 400, array $error = [] ): JsonResponse { return response()->json([ 'success' => false, 'message' => $message, 'error' => [ 'code' => $code, 'details' => $error['details'] ?? null, ], ], $code); } public static function validate( bool $condition, string $message = 'Validation failed', int $code = 422, array $extra = [] ): ?JsonResponse { return $condition ? null : self::error($message, $code, $extra); } public static function response($type = '', $query = '', $key = ''): array { $debug = app()->environment('local') && request()->is('api/*'); $result = match ($type) { 'get' => $key ? $query->get()->keyBy($key) : $query->get(), 'getSub' => $query->get(), 'count' => $query->count(), 'first' => $query->first(), 'success' => 'Success', 'result' => $query, default => null, }; if ($type == 'getSub') { $array = $result->map(function ($item) { return (array) $item; })->toArray(); foreach ($array as $row) { $data[$row[$key]][] = $row; } $result = $data ?? []; } $response['data'] = $result; $response['query'] = $debug ? self::debugQueryLog() : []; // 다음 요청에 로그가 섞이지 않도록 비워준다 (로컬에서만 의미있음) if ($debug) { DB::flushQueryLog(); } return $response; } public static function handle( callable $callback, string $responseTitle = '요청' ): JsonResponse { try { $result = $callback(); // 이미 JsonResponse면 그대로 반환 if ($result instanceof JsonResponse) { return $result; } // [신규] 서비스가 에러 ‘신호 배열’을 반환한 경우 감지 // 허용 포맷 예: // ['error' => 'NO_TENANT', 'code' => 400] // ['code' => 404, 'message' => '데이터 없음'] if (is_array($result) && ( array_key_exists('error', $result) || (array_key_exists('code', $result) && is_numeric($result['code']) && (int) $result['code'] >= 400) ) ) { $code = (int) ($result['code'] ?? 400); $message = (string) ($result['message'] ?? ($result['error'] ?? '서버 에러')); $details = $result['details'] ?? null; // 에러에도 쿼리 로그 포함되도록 error()가 처리하게 맡김 return self::error($message, $code, ['details' => $details]); } // 표준 박스( ['data'=>..., 'query'=>...] ) 하위호환 if (is_array($result) && array_key_exists('data', $result)) { $data = $result['data']; $debug = $result['query'] ?? []; } else { // 그냥 도메인 결과만 반환한 경우 $data = $result; $debug = (app()->environment('local') && request()->is('api/*')) ? self::debugQueryLog() : []; } return self::success($data, $responseTitle, $debug); } catch (\Throwable $e) { // HttpException 계열은 상태코드/메시지를 그대로 반영 if ($e instanceof HttpException) { return self::error( $e->getMessage() ?: '서버 에러', $e->getStatusCode(), ['details' => config('app.debug') ? $e->getTraceAsString() : null] ); } return self::error('서버 에러', 500, [ 'details' => $e->getMessage(), ]); } } }