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.