Laravel 8: Can I make Eloquent scope but NOT against query builder but against related model?

Viewed 268

I have a model - let's call it Parent.

Each Parent can have many children.

public function children(): HasMany
{
    return $this->hasMany(Child::class, 'parent_id', 'id');
}

I want to make a scope for Parent called "active".

My requirement goes as follows:

Parent is active when it has at least 1 child.

I've done local scopes multiple times and I know that within Parent.php I can do something like:

public function scopeActive($query)
{
    return $query->where(…);
}

But as you see, $query is a \Illuminate\Database\Eloquent\Builder which is not my case. I want to operate on related model somehow, not the DB query.

Can I do this in a clean way without fetching all parents with('child') and within ->filter() forgetting those that have no children? When there will be 1000 parents but only one will have children, it will simply waste DB resources (by fetching 999 redundant parents).

4 Answers

You can use the following query

public function scopeActive($query)
{
    return $query->has('children');
}

One option is to use whereHas in scope:

public function scopeActive($query){
  return $query->whereHas('children');
}

OR

public function scopeActive(){
  return $this->whereHas('children');
}

And

Parent::active()->with('children')->get();

should give you all Parents who have children and along with respective children

Can you try something like:

public function getActiveAttribute() {
  return $this->children()->count() > 1;
}

This can be used like,

$parent->active

And the query will only be made when you'll try to access the active property on the Parent model, not when you will be fetching all parents.

In Parent

public function getActiveAttribute() {
  return $this-> children()->exists();
}

In code

$parent = new Parent;
if($parent->active){//true}

You can also use count

count($this->children); // 0 evaluates to false

a related thread here if you need: Laravel Check If Related Model Exists

Related