I have a User
model and a Blocklist
model, Now when I call User::all()
I only want to return Users who are not related based on records in the block list table.
For instance:
user
Table
id | ... |
---|---|
1 | ... |
2 | ... |
3 | ... |
4 | ... |
5 | ... |
blocklist
Table
id | user_id | blockable_id | blockable_type |
---|---|---|---|
1 | 1 | 2 | \App\Models\User |
2 | 1 | 3 | \App\Models\User |
2 | 5 | 1 | \App\Models\User |
User
Model
...
public function blocklist()
{
return $this->hasMany(Block::class);
}
Blocklist
Model
...
public function blockable(): MorphTo
{
return $this->morphTo();
}
UserController
...
$users = \App\Models\User::whereDoesntHave('blocklist', function (Builder $query) {
$query->where('user_id', auth('sanctum')->id());
$query->orWhere(function (Builder $query) {
$query->where('blockable_id', auth('sanctum')->id());
$query->where('blockable_type', User::class);
});
})->all();
The idea is that, if user: 1
is making this request they should not see user: 2
and user: 3
whom they have blocked and they should also not see user: 5
who has also blocked them, but this is not how it works, whatever I do all the users are still returned.
I think might this will help you, you had a small logic error in your query, instead of checking if the blockable_id is equal to auth user's id you should be checking if the user_id matches.
$users = \App\Models\User::whereDoesntHave('blocklist', function (Builder $query) {
$query->where('user_id', auth('sanctum')->id()); // Check if the authenticated user is blocking someone
$query->orWhere(function (Builder $query) {
$query->where('blockable_id', auth('sanctum')->id()); // Check if someone is blocking the authenticated user
$query->where('blockable_type', User::class);
});
})->get();