Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel - reverse polymorphic relationship

I basically have two models (dog and cat) of the same type: pets. The table pets joins all dogs and cats in the database. Now I would like to be able to find a specific pet through the pet id in the PetController. Like so:

$pet = Pet::findOrFail($id); // returns a dog or cat

Tables structure:

┌──────────────┐  ┌───────────┐  ┌───────────┐
│ pets         │  │ dogs      │  │ cats      │
├──────────────┤  ├───────────┤  ├───────────┤
│ id           │  │ id        │  │ id        │
│ related_type │  │ name      │  │ name      │
│ related_id   │  │ eye_color │  │ tail_size │
└──────────────┘  └───────────┘  └───────────┘

Pets table:

┌────┬──────────────┬────────────┐
│ id │ related_type │ related_id │
├────┼──────────────┼────────────┤
│ 1  │ dog          │ 1          │
├────┼──────────────┼────────────┤
│ 2  │ dog          │ 2          │
├────┼──────────────┼────────────┤
│ 3  │ cat          │ 1          │
└────┴──────────────┴────────────┘

I have searched the Laravel docs but none of the relationships seem to fit for this problem. Only the polymorphic relationship would work the other way around, so that I could access the pet model through the dog- or cat-id. But I am looking for a solution that work the other way around. Is there any kind of relationship without needing to use nasty if-else in the PetController manually?

Thank you!

like image 642
pixelmusic Avatar asked Jul 12 '18 10:07

pixelmusic


People also ask

What is polymorphic relationship in Laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.

What is with () in Laravel?

with() function is used to eager load in Laravel. Unless of using 2 or more separate queries to fetch data from the database , we can use it with() method after the first command. It provides a better user experience as we do not have to wait for a longer period of time in fetching data from the database.

What is BelongsTo in Laravel?

BelongsTo is a inverse of HasOne. We can define the inverse of a hasOne relationship using the belongsTo method. Take simple example with User and Phone models. I'm giving hasOne relation from User to Phone. class User extends Model { /** * Get the phone record associated with the user.

What is MorphTo in Laravel?

"MorphTo" is used to define the relationship from a one-to-one or one-to-many polymorphic table to whichever model or models it is linked to. https://laravel.com/docs/5.7/eloquent-relationships#one-to-many-polymorphic-relations.


1 Answers

You can define a polymorphic relationship between these 3 models like this

Pet Model

public function related(){
     $this->morphTo();
}

Dog Model

public function pets(){
     $this->morphMany('App\Pet', 'related');
}

Cat Model

public function pets(){
     $this->morphMany('App\Pet', 'related');
}

Now fetch it like this

$pet = Pet::findOrFail($id)->related;
dd($pet); //you will get either cat or dog

Easy create

$dog = Dog::create(['name'=> 'dog1', 'eye_color' => 'gray']);
$dog->pets()->create();

Check details here https://laravel.com/docs/5.6/eloquent-relationships#polymorphic-relations

like image 118
rkj Avatar answered Oct 03 '22 20:10

rkj