Laravel Eloquent – Filtering results and eager loaded results

So here is the use case:

You have users and they have many addresses. Say you want to filter and eager load on addresses (say…only US addresses). In order to do so you have to filter the eager load AND filter using whereHas so your result set is only those users with US addresses and only their US addresses are returned. This seems a bit clunky.

Here is an example:

(new AppUser)
    ->with(['address' => function(){/* filter code */}])
    ->whereHas('address', function(){/* pretty much the same filter code */})
    ->get()

Is there a better way to do this? I feel like I am missing something.

You’re confusing whereHas and with.

The with method will let you load the relationship only if the query returns true.

The whereHas method will let you get only the models which have the relationship which returns true to the query.

So here :

(new AppUser)->with(['address' => function($query){/* filter code */}])->get();

will return all the users, but will only eager load the address when the filter code returns true.

And here :

(new AppUser)->whereHas('address', function($query){/* filter code */})->get();

will return only the Users which have their relationship “address” returning true on the filter code.

7

You’re aware you can create custom relationships like? :

    class User extends Model implements...
    {
     ....

          function USAddresses(){
          return $this->
              belongsToMany(User::class,UserAddresses::class,'user_id','address_id')
              ->withPivot('postal_code')
              ->wherePivot('postal_code', !null );
     }
    } // end model

In your controller then:

    $this->users->with('USAddresses')->whereHas(...)->get();

This way, you have your filters already ready already. ( :

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *