query('thread'); if (is_string($threadParam)) { $threadId = $this->parseIriId($threadParam); if ($threadId !== null) { $query->where('thread_id', $threadId); } } $posts = $query ->oldest('created_at') ->get() ->map(fn (Post $post) => $this->serializePost($post)); return response()->json($posts); } public function store(Request $request): JsonResponse { $data = $request->validate([ 'body' => ['required', 'string'], 'thread' => ['required', 'string'], ]); $threadId = $this->parseIriId($data['thread']); $thread = Thread::findOrFail($threadId); $post = Post::create([ 'thread_id' => $thread->id, 'user_id' => $request->user()?->id, 'body' => $data['body'], ]); return response()->json($this->serializePost($post), 201); } public function destroy(Post $post): JsonResponse { $post->delete(); return response()->json(null, 204); } private function parseIriId(?string $value): ?int { if (!$value) { return null; } if (preg_match('#/threads/(\d+)$#', $value, $matches)) { return (int) $matches[1]; } if (is_numeric($value)) { return (int) $value; } return null; } private function serializePost(Post $post): array { return [ 'id' => $post->id, 'body' => $post->body, 'thread' => "/api/threads/{$post->thread_id}", 'user_id' => $post->user_id, 'created_at' => $post->created_at?->toIso8601String(), 'updated_at' => $post->updated_at?->toIso8601String(), ]; } }