milo526
milo526

Reputation: 5083

Load laravel model where relationship has condition

I was wondering how I could load all models of a type where a specific conditions is met.
Lets take the following example setup. I have 2 eloquent models, House and Rental. A House has a hasMany relationship to the Rental.

public function rentals()
{
    return $this->hasMany(Rental::class);
}

The Rental class has a review column which can have the following values: positive or negative.

Now I'd like to "override" the default query builder which can be done using:

public function newQuery($excludeDeleted = true) {
    return parent::newQuery($excludeDeleted);
}

Note: this does not change the default behaviour.

I'd like to know how I can change the default House query to only return the House instances which have at least any arbitrary number (x) Rentals with a review equal to positive.

So House::all() should only return Houses with at least x positive Rentals.

Bonuspoints if you can also explain how to add another function which can be used to query all Houses

My question seems to have a lot in common with the softDeletes trait of Laravel, softDeletes models only query models where the deleted_at column is non null. The bonus part of my question can be seen as the ::withTrashed() option on a query.
The application is build on Laravel 5.4.

Upvotes: 1

Views: 2494

Answers (1)

user1669496
user1669496

Reputation: 33048

You'd want to use whereHas to load the houses that meet certain criteria.

$houses = House::whereHas('rentals', function($q) {
    $q->where('review', 'positive');
}, '>=', $x)->get();

Here, $x is the number of positive reviews a house must have before it shows up.

It's pretty simple so I'm not sure if it's still a candidate for adding this condition as default since you also want to be able to remove the default too at times. Perhaps the better solution is to drop this in a function in the House model which you can re-use and not worry about having it work by default.

Upvotes: 4

Related Questions