A MorphOne relationship is a one-to-one polymorphic relationship, where a model can belong to more than one type of model using a single association.

Real-World Examples

  • User → Profile Image
  • Product → Image
  • Blog Post → Thumbnail
  • Course → Banner Image

Instead of creating multiple image tables, we use one images table.

1.When to Use morphOne

Use morphOne when:

  • One model has only one related record
  • Multiple models share the same related table
  • You want clean & reusable database design

2. Example Scenario (User & Product Image)

User ─┐
├── Image
Product

✔ One image table
✔ Many parent models

3. Database Structure

users table

id
name

products table

id
title

images table (Polymorphic)

id
imageable_id
imageable_type
path
created_at

📌 imageable_id → parent ID
📌 imageable_type → parent model class

4.Create Models & Migrations

php artisan make:model Image -m
php artisan make:model User -m
php artisan make:model Product -m

images migration

Schema::create('images', function (Blueprint $table) {
$table->id();
$table->morphs('imageable'); // creates imageable_id & imageable_type
$table->string('path');
$table->timestamps();
});

Run:

php artisan migrate

5.Define Relationships in Models

Image.php

class Image extends Model
{
public function imageable()
{
return $this->morphTo();
}
}

User.php

class User extends Model
{
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
}

Product.php

class Product extends Model
{
public function image()
{
return $this->morphOne(Image::class, 'imageable');
}
}

6.How Laravel Stores Data

Column Value
imageable_id 1
imageable_type App\Models\User

or

| imageable_id | 5 |
| imageable_type | App\Models\Product |

7.Create MorphOne Record

Add image to user

$user = User::find(1);

$user->image()->create([
'path' => 'uploads/users/avatar.png'
]);

imageable_id auto-filled
imageable_type auto-filled

Add image to product

$product->image()->create([
'path' => 'uploads/products/item.png'
]);

8.Fetch Related Data

Get user image

$user->image;

Access image path

$user->image->path;

9.Update MorphOne Record

$user->image->update([
'path' => 'uploads/users/new-avatar.png'
]);

10.Delete MorphOne Record

$user->image()->delete();

11.Eager Loading (Performance)

$users = User::with('image')->get();

12.Real LMS Example (Course Banner)

Course.php

public function banner()
{
return $this->morphOne(Image::class, 'imageable');
}

Usage

$course->banner->path;

13.Rename Morph Type (Optional)

Relation::morphMap([
'user' => User::class,
'product' => Product::class,
]);

Stored as:

imageable_type = 'user'

Categorized in:

Laravel,