Home Arrow Icon Knowledge base Arrow Icon Global Arrow Icon How do you use the morphOne method in Laravel for polymorphic relationships


How do you use the morphOne method in Laravel for polymorphic relationships


The `morphOne` method in Laravel is used to define a one-to-one polymorphic relationship between models. This allows a model to belong to more than one other model on a single association, but only one related model at a time.

How to Use `morphOne` in Laravel

Database Structure

For a one-to-one polymorphic relationship, your related table needs two special columns:
- `imageable_id` (integer): stores the ID of the related model.
- `imageable_type` (string): stores the class name of the related model.

For example, if you have a polymorphic `Image` model related to both `Post` and `User` models, your `images` table would have these two columns to identify which model each image belongs to[1].

Defining the Relationship in Models

1. In the child model (e.g., Image):
Use the `morphTo` method to define the inverse of the polymorphic relation:

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

2. In the parent models (e.g., Post and User):
Use the `morphOne` method to define the one-to-one polymorphic relation:

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

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

The second parameter `'imageable'` in `morphOne` matches the prefix of the polymorphic columns (`imageable_id` and `imageable_type`) in the `images` table[1][3].

Accessing the Relationship

- To get the image of a post:

php
  $post = Post::find(1);
  $image = $post->image;
  

- To get the parent model (post or user) of an image:

php
  $image = Image::find(1);
  $parent = $image->imageable; // returns either a Post or User instance
  

Advanced Usage: One of Many (Polymorphic)

Laravel also supports retrieving a single related model from many using `morphOne` combined with helper methods like `latestOfMany()`, `oldestOfMany()`, or `ofMany()`.

For example, to get the latest image of a user:

php
public function latestImage(): MorphOne
{
    return $this->morphOne(Image::class, 'imageable')->latestOfMany();
}

Or to get the image with the most likes:

php
public function bestImage(): MorphOne
{
    return $this->morphOne(Image::class, 'imageable')->ofMany('likes', 'max');
}

These methods help retrieve a single "one of many" related model based on sorting or aggregation criteria[1][3].

In summary, `morphOne` is used on the parent model to define a one-to-one polymorphic relationship, specifying the related model and the polymorphic type prefix. The child model uses `morphTo` to define the inverse relation. This setup allows a model like `Image` to belong to multiple different models (`Post`, `User`, etc.) through a single association. Advanced use cases include retrieving the latest, oldest, or best related model using helper methods chained to `morphOne`[1][3].

Citations:
[1] https://laravel.com/docs/11.x/eloquent-relationships
[2] https://www.sitepoint.com/eloquents-polymorphic-relationships-explained/
[3] https://blog.logrocket.com/polymorphic-relationships-laravel/
[4] https://stackoverflow.com/questions/65630548/how-to-have-multiple-same-polymorphic-relations-in-one-model-in-php-laravel
[5] https://www.reddit.com/r/laravel/comments/mlnqld/i_need_help_with_laravel_one_to_one_polymorphic/
[6] https://stackoverflow.com/questions/69588698/laravel-polymorphic-relationships-issue
[7] https://www.sitepoint.com/what-are-polymorphic-relations-and-how-do-we-use-them-with-eloquent/
[8] https://laracasts.com/discuss/channels/laravel/polymorphic-relationship-is-not-inserting-type-in-database