如何使用Eloquent排除user表中含指定角色的数据行
Eloquent查询排除role字段特定值的实现方案
下面是几种不同场景下的可用实现,你可以根据业务复用需求选择:
- 单次查询临时过滤
最直接的方式,只需要在构建查询时手动加条件即可,适合仅个别查询需要过滤的场景:
单角色排除用where:
多角色排除用// 排除role为banned的用户 $users = User::where('role', '!=', 'banned')->get();whereNotIn:// 同时排除admin、guest两类角色 $users = User::whereNotIn('role', ['admin', 'guest'])->get(); - 本地作用域复用过滤逻辑
如果这个过滤规则需要在多个查询里重复用,可以在User模型中定义本地查询作用域,避免重复写条件:
先在app/Models/User.php里加对应scope方法:
用的时候直接调用作用域即可,不传参默认排除封禁用户,传参可以自定义要排除的角色:/** * 排除指定角色的查询作用域 * @param mixed $query * @param array $excludedRoles 要排除的角色列表,默认排除封禁账号 * @return mixed */ public function scopeWithoutRoles($query, array $excludedRoles = ['banned']) { return $query->whereNotIn('role', $excludedRoles); }// 默认排除banned角色 $normalUsers = User::withoutRoles()->paginate(15); // 自定义排除admin、super_admin角色 $frontUsers = User::withoutRoles(['admin', 'super_admin'])->get(); - 全局作用域默认全局过滤
如果业务要求所有查询User表的场景默认都要排除某类角色(比如所有前台、接口查询都不返回被封禁的用户),可以用全局作用域,一次配置之后所有查询默认带上过滤条件,不会因为漏写条件查出不符合要求的数据。
直接在User模型的booted方法中注册全局作用域即可:
配置后常规查询默认自动过滤,如果遇到特殊场景(比如后台需要查看所有被封禁用户),可以临时移除全局作用域:protected static function booted() { // 注册全局作用域,默认所有查询排除banned角色 static::addGlobalScope('exclude_banned_user', function ($query) { $query->where('role', '!=', 'banned'); }); }// 移除指定全局作用域,查询包含被封禁用户在内的所有数据 $allUsers = User::withoutGlobalScope('exclude_banned_user')->get();
注意:不要和模型的
$hidden属性搞混,$hidden是序列化输出时隐藏指定字段,不会在SQL查询阶段过滤数据行,达不到排除整行数据的效果。
内容的提问来源于stack exchange,提问作者Zen3x
相关产品推荐
相关产品推荐

