Here is a sample database-table (users
):
id - int(11) auto_increment
name - varchar(100)
banned - int(1)
The column banned
is a boolean value which is 0
(false
) by default. If an user has been banned, the value is 1
.
I'd like to exclude any banned users from all queries by default. I could create a query scope and then use that everywhere. However, I'd much more prefer simply having that check on by default.
I could also create a newQuery
-method of my own, like so:
// Inside User-model, which extends Eloquent
public function newQuery($excludeDeleted = true)
{
$builder = parent::newQuery($exludeDeleted);
$builder->where('banned', '=', '0');
return $builder;
}
However, this way I wouldn't be able to switch off this behaviour. I might want to see the banned users in my private admin panel, but would not be able to, as this restriction would be applied to any query done via Eloquent.
Any idea on how to solve this problem?
Replying here for others that may be looking for a similar answer.
You can create a global scope, have the model use the global scope by default, then use the withoutGlobalScope
when you want to make a query without that scope applied.
See Laravel docs: https://laravel.com/docs/5.8/eloquent#global-scopes
So in your case you would create a new global scope to query users that are not banned.
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class ExcludeBannedScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('banned', '=', 0);
}
}
Apply the global scope to your User model.
<?php
namespace App;
use App\Scopes\ExcludeBannedScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booting" method of the model.
*
* @return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new ExcludeBannedScope);
}
}
This will now added the where banned = 0
to all queries.
In your admin section where you want to see all users including banned you can do
User::withoutGlobalScope(\App\Scopes\ExcludeBannedScope::class)->get();
Laravel provides Global Scopes for exactly this purpose. From the docs:
class AgeScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
return $builder->where('age', '>', 200);
}
}
class User extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(new AgeScope);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With