$dto->userId, 'title' => $dto->title, 'body' => $dto->body, 'created_at' => $dto->createdAt, ]); return $this->toDomain($model); } public function find(int $id): ?Post { $model = PostModel::find($id); return $model === null ? null : $this->toDomain($model); } /** * @return Post[] */ public function findByUserId(int $userId): array { $models = PostModel::query() ->where('user_id', $userId) ->orderBy('created_at', 'desc') ->get(); return $models->map( function (PostModel $model) { return $this->toDomain($model); }, )->all(); } /** * @return Post[] */ public function findRecent(int $limit): array { $models = PostModel::query() ->orderBy('created_at', 'desc') ->limit($limit) ->get(); return $models->map( function (PostModel $model) { return $this->toDomain($model); }, )->all(); } public function delete(int $id): void { PostModel::query()->where('id', $id)->delete(); } /** * @throws RuntimeException */ public function update(Post $post): Post { $model = PostModel::find($post->getId()); if ($model === null) { throw new RuntimeException( "Post with id: {$post->getId()} does not exist" ); } $model->user_id = $post->getUserId(); $model->title = $post->getTitle(); $model->body = $post->getBody(); $model->created_at = $post->getCreatedAt(); $model->feature_slot = $post->getFeatureSlot(); $model->save(); return $this->toDomain($model); } public function findByFeatureSlot(int $slot): ?Post { $model = PostModel::query() ->where('feature_slot', $slot) ->first(); return $model === null ? null : $this->toDomain($model); } /** * @return Post[] */ public function findFeatured(): array { $models = PostModel::query() ->whereNotNull('feature_slot') ->orderBy('feature_slot', 'asc') ->get(); return $models->map( function (PostModel $model) { return $this->toDomain($model); }, )->all(); } private function toDomain(PostModel $model): Post { $utc = new DateTimeZone('UTC'); return new Post( id: $model->id, userId: $model->user_id, title: $model->title, body: $model->body, createdAt: new DateTimeImmutable( $model->created_at->toDateTimeString(), $utc, ), featureSlot: $model->feature_slot, ); } }