Files
sam-docs/changes/2025-12-15_items-api-files-fix.md
hskwon 3d6d7b67ea docs: changes/plans 문서 현황 최신화
- changes/2025-12-15: 체크리스트 완료 표시
- plans/items-table-unification: 전체 Phase 완료 상태로 업데이트
2025-12-16 09:56:36 +09:00

7.0 KiB

Items API files 배열 에러 수정

날짜

2025-12-15

문제

PUT /api/v1/items/{id} 요청 시 500 에러 발생

"Array to string conversion"

원인 분석

  1. API 요청에서 files 배열이 전송됨:
{
  "files": {
    "drawing": [{
      "id": 5,
      "file_name": "IMG_2163.png",
      "file_path": "287/items/2025/12/ec3483f4152d1eb1.png"
    }]
  }
}
  1. ItemsService::getKnownFields()$apiFieldsfiles가 없어서 동적 필드로 인식됨

  2. extractDynamicOptions()에서 files가 "알려지지 않은 필드"로 추출됨

  3. $product->update($data) 호출 시 files 배열이 그대로 전달되어 DB 저장 시 에러 발생

수정 파일

api/app/Services/ItemsService.php

수정 내용

1. getKnownFields() 메서드 (라인 36-37)

// 수정 전
$apiFields = ['item_type', 'type_code', 'bom', 'product_type'];

// 수정 후
$apiFields = ['item_type', 'type_code', 'bom', 'product_type', 'files'];

2. updateProduct() 메서드 (라인 729-730)

// 수정 전
unset($data['item_type']);

// 수정 후
unset($data['item_type'], $data['files']);

3. updateMaterial() 메서드 (라인 771-772)

// 수정 전
unset($data['item_type'], $data['code']);

// 수정 후
unset($data['item_type'], $data['code'], $data['files']);

적용 체크리스트

  • getKnownFields() - $apiFields'files' 추가
  • updateProduct() - unset()$data['files'] 추가
  • updateMaterial() - unset()$data['files'] 추가

커밋 정보

c68c280 fix: Items API 수정 시 files 배열로 인한 500 에러 수정

관련 파일

  • api/app/Http/Controllers/Api/V1/ItemsController.php
  • api/app/Http/Controllers/Api/V1/ItemsFileController.php

ItemsFileController delete 메서드 타입 에러 수정

날짜

2025-12-15

문제

DELETE /api/v1/items/{id}/files/{fileId} 요청 시 타입 에러 발생

Argument #2 ($fileId) must be of type int, string given

원인 분석

Laravel 라우트 파라미터는 기본적으로 string으로 전달되는데, 컨트롤러 메서드에서 int 타입힌트를 사용하여 에러 발생

수정 파일

api/app/Http/Controllers/Api/V1/ItemsFileController.php

수정 내용

delete() 메서드 (라인 157-159)

// 수정 전
public function delete(int $id, int $fileId, Request $request)
{
    return ApiResponse::handle(function () use ($id, $fileId, $request) {

// 수정 후
public function delete(int $id, mixed $fileId, Request $request)
{
    $fileId = (int) $fileId;

    return ApiResponse::handle(function () use ($id, $fileId, $request) {

적용 체크리스트

  • delete() 메서드 - $fileId 파라미터 타입을 mixed로 변경
  • delete() 메서드 - 내부에서 $fileId = (int) $fileId; 캐스팅 추가

커밋 정보

1040ce0 fix: ItemsFileController delete 메서드 타입 에러 수정

ItemsFileController userId null 처리

날짜

2025-12-15

문제

DELETE /api/v1/items/{id}/files/{fileId} 요청 시 500 에러 발생

softDeleteFile(): Argument #1 ($userId) must be of type int, null given

원인 분석

  • auth()->id()null을 반환
  • API 키 인증만 사용하고 Sanctum 토큰 인증이 없는 경우 발생
  • softDeleteFile(int $userId) 메서드에 null 전달 시 타입 에러

수정 파일

api/app/Http/Controllers/Api/V1/ItemsFileController.php

수정 내용

1. upload() 메서드 (라인 77)

// 수정 전
$userId = auth()->id();

// 수정 후
$userId = auth()->id() ?? app('api_user');

2. delete() 메서드 (라인 163)

// 수정 전
$userId = auth()->id();

// 수정 후
$userId = auth()->id() ?? app('api_user');

적용 체크리스트

  • upload() 메서드 - auth()->id() ?? app('api_user') 변경
  • delete() 메서드 - auth()->id() ?? app('api_user') 변경

커밋 정보

22abb99 fix: ItemsFileController userId null 처리 추가

ItemsFileController 파일 삭제 로직 일원화

날짜

2025-12-15

문제

  • upload() 메서드의 파일 교체 삭제와 delete() 메서드의 파일 삭제 로직이 분리되어 있음
  • userId 캐스팅이 일관되지 않음 (upload에만 int 캐스팅 적용)
  • 관리 포인트가 2곳으로 분산

수정 파일

api/app/Http/Controllers/Api/V1/ItemsFileController.php

수정 내용

1. deleteFile() private 메서드 추가 (라인 195-199)

// 추가
private function deleteFile(File $file): void
{
    $userId = (int) (auth()->id() ?? app('api_user'));
    $file->softDeleteFile($userId);
}

2. upload() 메서드 - 기존 파일 교체 시 (라인 98-100)

// 수정 전
if ($existingFile) {
    $existingFile->softDeleteFile($userId);
    $replaced = true;
}

// 수정 후
if ($existingFile) {
    $this->deleteFile($existingFile);
    $replaced = true;
}

3. delete() 메서드 (라인 180-181)

// 수정 전
$userId = auth()->id() ?? app('api_user');
...
$file->softDeleteFile($userId);

// 수정 후
// $userId 변수 제거
$this->deleteFile($file);

적용 체크리스트

  • deleteFile() private 메서드 추가
  • upload() 메서드 - $this->deleteFile($existingFile) 사용
  • delete() 메서드 - $userId 변수 제거, $this->deleteFile($file) 사용

커밋 정보

dea414b refactor: ItemsFileController 파일 삭제 로직 일원화

ItemsFileController 파일 다운로드 URL 수정

날짜

2025-12-15

문제

파일 다운로드 시 인증 오류 발생

  • 생성되는 URL: /api/v1/files/download/{base64_path} (라우트 없음)
  • 실제 라우트: /api/v1/files/{id}/download

수정 파일

api/app/Http/Controllers/Api/V1/ItemsFileController.php

수정 내용

1. getFileUrl() 메서드 (라인 244-247)

// 수정 전
private function getFileUrl(string $filePath): string
{
    return url('/api/v1/files/download/'.base64_encode($filePath));
}

// 수정 후
private function getFileUrl(int $fileId): string
{
    return url("/api/v1/files/{$fileId}/download");
}

2. formatFileResponse() 메서드 (라인 232)

// 수정 전
'file_url' => $this->getFileUrl($file->file_path),

// 수정 후
'file_url' => $this->getFileUrl($file->id),

3. upload() 응답 (라인 142)

// 수정 전
'file_url' => $this->getFileUrl($filePath),

// 수정 후
'file_url' => $this->getFileUrl($file->id),

적용 체크리스트

  • getFileUrl() 메서드 - 파라미터를 string $filePathint $fileId로 변경
  • getFileUrl() 메서드 - URL 형식을 /api/v1/files/{id}/download로 변경
  • formatFileResponse() - $this->getFileUrl($file->id) 사용
  • upload() 응답 - $this->getFileUrl($file->id) 사용

프론트엔드 참고

  • 다운로드 요청 시 API 키 헤더 필수 (X-API-Key 또는 설정된 헤더)
  • 기존 FileStorageController의 download 라우트 활용

커밋 정보

98262ed fix: ItemsFileController 파일 다운로드 URL을 file_id 기반으로 변경