Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to select all rows except (A and B) in Eloquent ORM using Scope?

I'm trying to figure out how to get all rows except few (A and B) in Eloquent ORM modal.

User Model

public function notifications()
{
    return $this->hasMany('notification','listener_id','id');
}

Model Notification

public function scopeFriendship($query)
{
    return $query->where('object_type', '=', 'Friendship Request');
}

public function scopeSent($query)
{
    return $query->where('verb', '=', 'sent');
}

Here how can I get all notifications of a user except other than (Friendship and Sent) scope.

Something like:- all rows except !(Friendship AND Sent)
like image 678
Bit_hunter Avatar asked Jan 24 '26 00:01

Bit_hunter


1 Answers

It is possible to use scopes in combination with eager loading. Like that:

User::with(['notifications' => function($q){
    $q->friendship();
}])->get();

However we now need to invert the scope somehow. I can think of two ways to solve this.

1. Add negative scopes

public function scopeNotFriendship($query){
    return $query->where('object_type', '!=', 'Friendship Request');
}

public function scopeNotSent($query){
    return $query->where('verb', '!=', 'sent');
}

User::with(['notifications' => function($q){
    $q->notFriendship();
    $q->notSent();
}])->get();

2. Optional parameter

Or you could introduce an optional parameter to your current scopes. Something like this:

public function scopeFriendship($query, $is = true)
{
    return $query->where('object_type', ($is ? '=' : '!='), 'Friendship Request');
}

public function scopeSent($query, $is = true)
{
    return $query->where('verb', ($is ? '=' : '!='), 'sent');
}

This way you would only have to pass in false:

User::with(['notifications' => function($q){
    $q->friendship(false);
    $q->sent(false);
}])->get();

Edit

You can even gain more control by adding a second parameter for the boolean (AND or OR of the where:

public function scopeFriendship($query, $is = true, $boolean = 'and')
{
    return $query->where('object_type', ($is ? '=' : '!='), 'Friendship Request', $boolean);
}

And if you wanted either scope to be true:

$q->friendship(true, 'or');
$q->sent(true, 'or');

2nd Edit

This one finally worked (from the chat)

Notification::where('listener_id', $user_id) 
    ->where(function($q){ 
        $q->friendship(false) 
        $q->sent(false, 'or') 
    }) 
    ->get();
like image 137
lukasgeiter Avatar answered Jan 26 '26 17:01

lukasgeiter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!