Laravel Basic
Laravel Form
Laravel Database
Laravel Advance
Review
) to belong to multiple other models (like Product
, Hotel
, Movie
, Book
) using the same relation.That means:
reviews
), instead of creating separate tables like product_reviews
, hotel_reviews
, etc.Flow diagram
Use this command to generate a migration for creating a tables:
php artisan make:migration create_polymorphic_one_to_many_tables
public function up(): void { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); $table->text('description')->nullable(); $table->timestamps(); }); Schema::create('hotels', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('location')->nullable(); $table->timestamps(); }); Schema::create('movies', function (Blueprint $table) { $table->id(); $table->string('title'); $table->year('release_year')->nullable(); $table->timestamps(); }); Schema::create('reviews', function (Blueprint $table) { $table->id(); $table->text('review_text'); $table->unsignedBigInteger('reviewable_id'); // Polymorphic ID $table->string('reviewable_type'); // Polymorphic Type $table->timestamps(); }); } public function down(): void { Schema::dropIfExists('reviews'); Schema::dropIfExists('movies'); Schema::dropIfExists('hotels'); Schema::dropIfExists('products'); }
Run Migration
php artisan migrate
id | name | description | created_at | updated_at |
---|
id | name | location | created_at | updated_at |
---|
id | title | release_year | created_at | updated_at |
---|
id | review_text | reviewable_id | reviewable_type | created_at | updated_at |
---|
Generate a model with Artisan:
php artisan make:model Review php artisan make:model Product php artisan make:model Hotel php artisan make:model Movie
This generates 4 files Review.php , Product.php ,Hotel.php and Movie.php
namespace App\Models; use Illuminate\Database\Eloquent\Model; class Review extends Model { protected $fillable = ['review_text']; public function reviewable() { return $this->morphTo(); } }
namespace App\Models; use App\Models\Review; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected $fillable = ['name', 'description']; public function reviews() { return $this->morphMany(Review::class, 'reviewable'); } }
namespace App\Models; use App\Models\Review; use Illuminate\Database\Eloquent\Model; class Hotel extends Model { protected $fillable = ['name', 'location']; public function reviews() { return $this->morphMany(Review::class, 'reviewable'); } }
namespace App\Models; use App\Models\Review; use Illuminate\Database\Eloquent\Model; class Movie extends Model { protected $fillable = ['title', 'release_year']; public function reviews() { return $this->morphMany(Review::class, 'reviewable'); } }
use App\Models\Hotel; use App\Models\Movie; use App\Models\Product; // Add review for a Product $product = Product::create(['name' => 'Laptop', 'description' => 'A high-end laptop']); $product->reviews()->create(['review_text' => 'Great Product!']); // Add review for a Hotel $hotel = Hotel::create(['name' => 'Grand Hotel', 'location' => 'New York']); $hotel = Hotel::find(1); $hotel->reviews()->create(['review_text' => 'Excellent stay!']); // Add review for a Movie $movie = Movie::create(['title' => 'Inception', 'release_year' => 2010]); $movie->reviews()->create(['review_text' => 'Mind-blowing movie!']);
id | name | description | created_at | updated_at |
---|---|---|---|---|
1 | Laptop | A high-end laptop | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
id | name | location | created_at | updated_at |
---|---|---|---|---|
1 | Grand Hotel | New York | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
id | title | release_year | created_at | updated_at |
---|---|---|---|---|
1 | Inception | 2010 | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
id | review_text | reviewable_id | reviewable_type | created_at | updated_at |
---|---|---|---|---|---|
1 | Great Product! | 1 | App\Models\Product | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
2 | Excellent stay! | 1 | App\Models\Hotel | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
3 | Mind-blowing movie! | 1 | App\Models\Movie | 2025-08-26 13:18:32 | 2025-08-26 13:18:32 |
use App\Models\Hotel; use App\Models\Movie; use App\Models\Product; $product = Product::find(1); foreach ($product->reviews as $review) { echo $review->review_text; } // Get hotel reviews $hotel = Hotel::find(1); foreach ($hotel->reviews as $review) { echo $review->review_text; } // Get movie reviews $movie = Movie::find(1); foreach ($movie->reviews as $review) { echo $review->review_text; } // Get Review with Parent $review = Review::find(1); echo $review->reviewable->name;
use App\Models\Hotel; use App\Models\Movie; use App\Models\Product; // Find review and update $review = Review::find(1); $review->update(['content' => 'Updated review content']); // Or Update via Product $product = Product::find(1); $product->reviews()->where('id', 1)->update(['review_text' => 'Updated review content']); // Or Update via Hotel $hostel = Hotel::find(1); $hostel->reviews()->where('id', 2)->update(['review_text' => 'Updated review content']); // Or Update via Movie $movie = Movie::find(1); $movie->reviews()->where('id', 3)->update(['review_text' => 'Updated review content']);
use App\Models\Hotel; use App\Models\Movie; use App\Models\Product; // Delete a review $review = Review::find(1); $review->delete(); // Delete all reviews for a Product $product = Product::find(1); $product->reviews()->where('id', 1)->delete(); // where condition delete $product->reviews()->delete(); // Delete all reviews // Delete all reviews for a Hotel $hotel = Hotel::find(1); $hotel->reviews()->where('id', 2)->delete(); // where condition delete $hotel->reviews()->delete(); // Delete all reviews // Delete all reviews for a Movie $movie = Movie::find(1); $movie->reviews()->where('id', 3)->delete(); // where condition delete $movie->reviews()->delete();
use App\Models\Hotel; use App\Models\Movie; use App\Models\Product; $product = Product::with('reviews')->find(1); foreach ($product->reviews as $review) { echo $review->review_text; } // Get hotel reviews $hotel = Hotel::with('reviews')->find(1); foreach ($hotel->reviews as $review) { echo $review->review_text; } // Get movie reviews $movie = Movie::with('reviews')->find(1); foreach ($movie->reviews as $review) { echo $review->review_text; } // Get Review with Parent $review = Review::with('reviewable')->find(1); echo $review->reviewable->name;
Always use with()
when fetching related data in bulk.