query('forum'); if (is_string($forumParam)) { $forumId = $this->parseIriId($forumParam); if ($forumId !== null) { $query->where('forum_id', $forumId); } } $threads = $query ->latest('created_at') ->get() ->map(fn (Thread $thread) => $this->serializeThread($thread)); return response()->json($threads); } public function show(Thread $thread): JsonResponse { return response()->json($this->serializeThread($thread)); } public function store(Request $request): JsonResponse { $data = $request->validate([ 'title' => ['required', 'string'], 'body' => ['required', 'string'], 'forum' => ['required', 'string'], ]); $forumId = $this->parseIriId($data['forum']); $forum = Forum::findOrFail($forumId); if ($forum->type !== 'forum') { return response()->json(['message' => 'Threads can only be created inside forums.'], 422); } $thread = Thread::create([ 'forum_id' => $forum->id, 'user_id' => $request->user()?->id, 'title' => $data['title'], 'body' => $data['body'], ]); return response()->json($this->serializeThread($thread), 201); } public function destroy(Thread $thread): JsonResponse { $thread->delete(); return response()->json(null, 204); } private function parseIriId(?string $value): ?int { if (!$value) { return null; } if (preg_match('#/forums/(\d+)$#', $value, $matches)) { return (int) $matches[1]; } if (is_numeric($value)) { return (int) $value; } return null; } private function serializeThread(Thread $thread): array { return [ 'id' => $thread->id, 'title' => $thread->title, 'body' => $thread->body, 'forum' => "/api/forums/{$thread->forum_id}", 'user_id' => $thread->user_id, 'created_at' => $thread->created_at?->toIso8601String(), 'updated_at' => $thread->updated_at?->toIso8601String(), ]; } }