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!

 

Афоризм дня:
Надо добавить еще: на тела основные природа все возлагает опять и в ничто не приводит. (509)
PHP

Leave a reply

Яндекс.Метрика