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

Čamo's avatar
Level 3

Is this Eloquent query right?

I found this query in one project I am facing right now but I am not sure what it actually does. It seems like a duplicate or redundant query.

$attributes = Attribute::with(['values.variants' => function ($query) use ($product) {
        $query->where('product_id', $product->id);
    }])->whereHas('values.variants', function($query) use ($product){
        $query->where('product_id', $product->id);
    })->get();

What is the difference between closure in with array and the whereHas() call. It seems like the same.

0 likes
5 replies
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

It looks correct.

Lets start with whereHas.. That checks that all Attribute MUST have values.variantswith that product ID.. So it ensures we get the right rows.

Secondly the with.. This eager loads the values.variantsfor each Attribute.. This wouldnt limit the query in any way, but just preloads the relationship.

The queries look kinda the same but has two similar but different objectives.

1 like
Čamo's avatar
Level 3

Thank you. Hope I understand.

MichalOravec's avatar

Sinnbeck has right they are complete different things.

If you want to avoid to duplicate code in the query then it could be

$attributes = Attribute::with(['values.variants' => $closure = function ($query) use ($product) {
    $query->where('product_id', $product->id);
}])->whereHas('values.variants', $closure)->get();

Where you save closure to the variable.

1 like
Sinnbeck's avatar

If you dont query get it, we can try playing with a real world scenario.

In a room are 5 men. 3 of them have a wife

Now you call in all men who have a wife (whereHas). So in comes 3 men.. Just the men Then you ask each man to go bring their wife.. So each of them go back to the other room to get their wife, one at the time.. Not very efficient.

So instead you call in all men with their wives (with).. Now in comes all 5 men, but 2 of them dont have a wife (but you did just say ALL men). So again. not efficient

Last you call in all men who have a wife (whereHas) and ask them to bring their wife (with).. And you get 3 men with 3 wives in one go :)

1 like

Please or to participate in this conversation.