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