Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Chron's avatar
Level 6

How to find for specific data in a many to many relationship?

I have three tables and all of them have many to many relationship.

Child have many Toys. Toys have many Models and vice versa.

What if I want to give the child a toy but before doing that, I want to validate if the child already has that toy with the same model. If it returns true then don't give the child that toy with that model.

0 likes
26 replies
ftiersch's avatar

Do you have a pivot table with all three foreign keys in it or do you have multiple pivot tables?

Chron's avatar
Level 6

I have model_toy and child_toy.

ftiersch's avatar
ftiersch
Best Answer
Level 28

You could do this on your Child model:

function hasToyWithModel($model) {
    return $this->toys()->whereHas('models', function ($query) use ($model) {
        $query->where('id', $model->id);
    })->exists();
}

I think that should work but I'm not sure if that's the most performant way.

Chron's avatar
Level 6

Ohh. I didn't knew you can do queries with a many to many relationship.

Do I need to have table child_model?

ftiersch's avatar

No, that query actually uses 2 subqueries (which could make it slow with a lot of data).

So basically it says "Check if this Child has a Toy that has at least one Model with the ID of the given model"

Chron's avatar
Level 6

But Toy has many to many relationship with Model. How does that query work?

ftiersch's avatar

With a subquery. Something like this:

SELECT * FROM child_toy WHERE EXISTS (SELECT * FROM model_toy WHERE model_id = ?)

Not sure about the exact syntax but something like that :)

Chron's avatar
Level 6

Ohhh...I understand it now. Thank you very much!

Chron's avatar
Level 6

@ftiersch What if I want to select all the child's toy with their model?

Does this work?

Child::with('toys.models')->find($id);
ftiersch's avatar

Yeah, that would work. You just put the name of the relationships in the with.

Chron's avatar
Level 6

What if the child was given a new toy with a new model?

I could do a sync in child_toy but how would I add the model?

ftiersch's avatar

You don't have to, it works with your existing model_toy relationship. with() also gets the values dynamically.

Chron's avatar
Level 6

Wait. So I just add the transaction to child_toy and it will already know what is its model?

ftiersch's avatar

Wait, I think you have an error in your database planning there.

One child can have multiple toys, right? But one toy can only be owned by a single child right? Also one toy is of a single Model but every Model can have multiple toys?

Chron's avatar
Level 6

By the way. What I mean by model is the brand. My naming just got messed up. Sorry.

Child can have multiple toys, A toy can be own by multiple children. A toy can have many brands and a brand can have many toys.

ftiersch's avatar

Aah okay. That makes more sense. But why can a toy have many brands? Isn't a toy usually by a single brand?

Anyway. In that case you would have to add the relation between toy and brand and between toy and child. The rest should work as expected then.

Chron's avatar
Level 6

In that case you would have to add the relation between toy and brand and between toy and child.

Yes. I have them. So when adding new child's toy, I just have to do this?

$child->toys()->sync([$id]);

and when fetching a specific child's toys and brands. I just have to do this?

Child::with('toys.brands')->find($id);

But why can a toy have many brands? Isn't a toy usually by a single brand?

Oh I did that because these toy names are ambiguous like Dinosaur, Ball, Truck etc.

ftiersch's avatar

If you add a new childs toy yes, that's all you need. But the toy needs to have all its brands already in the toy_brand relationship.

Chron's avatar
Level 6

Yes. Before giving a child the toy, the toy is already recorded in toy_brand relationship.

Chron's avatar
Level 6

Wait. The last model isn't fetched. I tried it just now.

Child::with('toys.brands')->get();

Childs' toys are fetched but the brands aren't.

ftiersch's avatar

Are your relationships (so the methods) called "toys()" and "brands()"? And does the brands() relationship work if you use it normally on a Toy model?

Chron's avatar
Level 6

Yes. It works when I do

Toy::with('brands')->get()

Wait. When I create toys, is this what I have to do?

Brands::find($id)->toys()->create([]);

Because when creating the toys, I did was :

$toy = Toy::create($request);
$toy->brands()->sync($request[$brand_id]);
ftiersch's avatar
$toy = Toy::create($request);
$toy->brands()->attach($brand_id);

Try this

Chron's avatar
Level 6

I tried it. It's still the same.

Chron's avatar
Level 6

I noticed that when I did this

Toy::with('brands')->find($id);

I get no brands. But it has data when I did Toy::with('brands')->get()

What could be the problem here?

Chron's avatar
Level 6

@ftiersch okay, I managed to fix the problem.

But when I run this, I get all the brands for the toy that the child has even if the brand is different.

Child::with('toys.brands')->find($child_id);

Please or to participate in this conversation.