feat: Phase 7.2 보완 - 나의 게시글 API 추가

- PostService.getMyPosts() 메서드 추가
- PostController.myPosts() 액션 추가
- GET /v1/posts/my 라우트 추가
- PostApi.php Swagger 문서 추가
This commit is contained in:
2025-12-19 16:27:36 +09:00
parent 4d3085e705
commit c15a245166
4 changed files with 72 additions and 0 deletions

View File

@@ -21,6 +21,19 @@ public function __construct(
protected PostService $postService protected PostService $postService
) {} ) {}
/**
* 나의 게시글 목록 조회
*/
public function myPosts()
{
return ApiResponse::handle(function () {
$filters = request()->only(['board_code', 'search', 'status']);
$perPage = (int) request()->get('per_page', 15);
return $this->postService->getMyPosts($filters, $perPage);
}, __('message.fetched'));
}
/** /**
* 게시글 목록 조회 * 게시글 목록 조회
*/ */

View File

@@ -324,4 +324,30 @@ public function getCustomFieldValues(int $postId): Collection
->with('field') ->with('field')
->get(); ->get();
} }
// =========================================================================
// 나의 게시글 메서드
// =========================================================================
/**
* 나의 게시글 목록 조회
*/
public function getMyPosts(array $filters = [], int $perPage = 15): LengthAwarePaginator
{
return Post::where('user_id', $this->apiUserId())
->where('tenant_id', $this->tenantId())
->with(['board:id,board_code,name'])
->when(isset($filters['board_code']), function ($q) use ($filters) {
$q->whereHas('board', fn ($query) => $query->where('board_code', $filters['board_code']));
})
->when(isset($filters['search']), function ($q) use ($filters) {
$q->where(function ($query) use ($filters) {
$query->where('title', 'like', "%{$filters['search']}%")
->orWhere('content', 'like', "%{$filters['search']}%");
});
})
->when(isset($filters['status']), fn ($q) => $q->where('status', $filters['status']))
->orderByDesc('created_at')
->paginate($perPage);
}
} }

View File

@@ -98,6 +98,34 @@
*/ */
class PostApi class PostApi
{ {
/**
* @OA\Get(
* path="/api/v1/posts/my",
* tags={"Post"},
* summary="나의 게시글 목록",
* description="로그인한 사용자가 작성한 모든 게시글을 조회합니다.",
* security={{"ApiKeyAuth":{}},{"BearerAuth":{}}},
*
* @OA\Parameter(name="board_code", in="query", description="게시판 코드 필터", @OA\Schema(type="string")),
* @OA\Parameter(name="search", in="query", description="제목/내용 검색", @OA\Schema(type="string")),
* @OA\Parameter(name="status", in="query", description="상태 필터", @OA\Schema(type="string", enum={"draft","published","hidden"})),
* @OA\Parameter(name="page", in="query", @OA\Schema(type="integer", example=1)),
* @OA\Parameter(name="per_page", in="query", @OA\Schema(type="integer", example=15)),
*
* @OA\Response(response=200, description="조회 성공",
*
* @OA\JsonContent(allOf={
*
* @OA\Schema(ref="#/components/schemas/ApiResponse"),
* @OA\Schema(@OA\Property(property="data", ref="#/components/schemas/PostPagination"))
* })
* ),
*
* @OA\Response(response=401, description="인증 실패", @OA\JsonContent(ref="#/components/schemas/ErrorResponse"))
* )
*/
public function myPosts() {}
/** /**
* @OA\Get( * @OA\Get(
* path="/api/v1/boards/{code}/posts", * path="/api/v1/boards/{code}/posts",

View File

@@ -1000,6 +1000,11 @@
Route::delete('/{code}/posts/{postId}/comments/{commentId}', [PostController::class, 'destroyComment'])->name('v1.boards.posts.comments.destroy'); // 댓글 삭제 Route::delete('/{code}/posts/{postId}/comments/{commentId}', [PostController::class, 'destroyComment'])->name('v1.boards.posts.comments.destroy'); // 댓글 삭제
}); });
// 게시글 API (사용자 중심)
Route::prefix('posts')->group(function () {
Route::get('/my', [PostController::class, 'myPosts'])->name('v1.posts.my'); // 나의 게시글 목록
});
}); });
// 공유 링크 다운로드 (인증 불필요 - auth.apikey 그룹 밖) // 공유 링크 다운로드 (인증 불필요 - auth.apikey 그룹 밖)