laravel
How to Create and Use Polymorphic Relationships in Laravel (1-to-1)
Polymorphic relationships in Laravel allow a model to belong to more than one other model on a single association. This is useful when you want to reuse the same model for different types of relationships. In this guide, we’ll create a simple example of a store with two product types: Carrots and Apples.
We'll be using Laravel 10 and PHP 8.3 for this tutorial.
Step 1: Setting Up Models and Migrations
1. Create the Product
Model and Migration
The Product
model will act as the shared parent for the polymorphic relationship.
Run the following command to generate the model and migration:
php artisan make:model Product -m
Update the migration file for products
:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name'); // Name of the product
$table->string('productable_type'); // Type of the related model
$table->unsignedBigInteger('productable_id'); // ID of the related model
$table->timestamps();
});
Update the Product
model:
class Product extends Model
{
protected $fillable = ['name'];
public function productable()
{
return $this->morphTo();
}
}
2. Create the Carrot
Model and Migration
Run the following command to generate the Carrot
model and migration:
php artisan make:model Carrot -m
Update the migration file for carrots
:
Schema::create('carrots', function (Blueprint $table) {
$table->id();
$table->string('color'); // Color of the carrot
$table->timestamps();
});
Update the Carrot
model:
class Carrot extends Model
{
protected $fillable = ['color'];
public function product()
{
return $this->morphOne(Product::class, 'productable');
}
}
3. Create the Apple
Model and Migration
Run the following command to generate the Apple
model and migration:
php artisan make:model Apple -m
Update the migration file for apples
:
Schema::create('apples', function (Blueprint $table) {
$table->id();
$table->string('taste'); // Taste of the apple
$table->timestamps();
});
Update the Apple
model:
class Apple extends Model
{
protected $fillable = ['taste'];
public function product()
{
return $this->morphOne(Product::class, 'productable');
}
}
Step 2: Running Migrations
Run the migrations to create the database tables:
php artisan migrate
This will create the following tables:
-
products
-
carrots
-
apples
Thus, the structure of the table will look like this:
products
| id | name | productable_type | productable_id |
carrots
| id | color |
apples
| id | taste |
Step 3: Creating Data
Here’s an example of how to create products with their specific types using Tinker:
Create a Carrot:
$carrot = Carrot::create(['color' => 'orange']);
$product = Product::create(['name' => 'Carrot', 'productable_type' => Carrot::class, 'productable_id' => $carrot->id]);
Create an Apple:
$apple = Apple::create(['taste' => 'sweet']);
$product = Product::create(['name' => 'Apple', 'productable_type' => Apple::class, 'productable_id' => $apple->id]);
Step 4: Retrieving Data
Get the Related Model from a Product:
$product = Product::find(1); // Assume this is a Carrot product
$details = $product->productable; // Returns the related Carrot model
echo $details->color; // Outputs: orange
Get the Product from a Specific Type:
$carrot = Carrot::find(1);
$product = $carrot->product;
echo $product->name; // Outputs: Carrot
Summary
With polymorphic relationships, you can efficiently manage models that share common traits while keeping their specific attributes in separate tables. In this example, we created a Product
model as the parent and linked it with Carrot
and Apple
models using a polymorphic relationship.
This structure is flexible and allows you to extend it further as your application grows. You can now reuse the Product
model for other product types if needed in the future.
Happy coding!
Leave a reply