validate([ 'content' => 'nullable|string|max:1000', 'stars' => 'nullable|integer|min:1|max:5', ]); if (!$request->filled('content') && !$request->filled('stars')) { throw ValidationException::withMessages([ 'content' => ['Provide a comment (content) and/or a rating (stars).'], ]); } $model = $this->getModel($type, $id); if (!$model) { return response()->json(['message' => 'Item not found'], 404); } $comment = null; if ($request->filled('content')) { $comment = $model->comments()->create([ 'user_id' => auth()->id(), 'content' => $data['content'], ])->load('user'); } $rating = null; if ($request->filled('stars')) { $rating = $model->ratings()->updateOrCreate( ['user_id' => auth()->id()], ['stars' => $data['stars']] ); } $model = $model->fresh(); return response()->json([ 'message' => 'Interaction saved successfully', 'comment' => $comment, 'your_rating' => $rating?->stars, 'average_rating' => $model->average_rating, 'ratings_count' => $model->ratings_count, 'comments_count' => $model->comments_count, ]); } private function getModel($type, $id) { // media, music and playlist all support comments + ratings. $models = [ 'music' => \App\Models\Music::class, 'media' => \App\Models\Media::class, 'playlist' => \App\Models\MusicPlaylist::class, ]; $class = $models[$type] ?? null; return $class ? $class::find($id) : null; } }