Laravel 11 中模型全局作用域通过独立类、闭包或重写 newQuery() 实现自动查询过滤;支持 withoutGlobalScope 精准排除或 withoutGlobalScopes 彻底禁用。

在 Laravel 11 中,模型全局作用域是实现自动过滤查询的核心机制。它能让所有对该模型的查询(如 get()、find()、where()、关联查询等)默认带上统一条件,避免重复写 where,也比手动拼接更安全可靠。
用独立作用域类注册(推荐标准做法)
适合需要复用、测试或跨模型共享的过滤逻辑,比如“仅活跃用户”“租户隔离”“多语言过滤”。
- 运行命令生成作用域类:
php artisan make:scope ActiveScope - 编辑
app/Scopes/ActiveScope.php,实现apply方法:public function apply(Builder $builder, Model $model) { $builder->where('status', 'active'); } - 在模型(如
User)的booted()方法中注册:protected static function booted() { static::addGlobalScope(new ActiveScope()); }
用闭包定义匿名作用域(轻量快捷)
适合简单、一次性场景,比如临时加个 is_published = true,不需额外文件。
- 在模型的
booted()中注册带键名的闭包:static::addGlobalScope('published', function (Builder $builder) { $builder->where('is_published', true); }); - 键名
'published'必须唯一,否则无法精准排除 - 该闭包会在模型首次加载时绑定,所有查询自动生效
重写 newQuery()(底层可控,绕过作用域链)
适用于需深度干预查询构建起点的场景,例如多语言自动按 App::getLocale() 过滤,或与软删除等内置作用域共存时避免冲突。
- 在模型中重写方法:
public function newQuery(): Builder { $query = parent::newQuery(); return $query->where('language', app()->getLocale()); } - 此方式不经过 Eloquent 的作用域系统,性能略高,也不受
withoutGlobalScopes()影响 - 注意:它对所有查询无差别生效,包括后台管理等需绕过过滤的场景,需额外设计开关逻辑
临时排除全局作用域(关键运维能力)
某些场景必须看到“原始数据”,比如后台列表、数据迁移、API 调试,这时要主动移除过滤。
- 排除指定类作用域:
User::withoutGlobalScope(ActiveScope::class)->get() - 排除闭包作用域:
User::withoutGlobalScope('published')->get() - 排除多个:
User::withoutGlobalScope([ActiveScope::class, 'published'])->get() - 彻底禁用全部:
User::withoutGlobalScopes()->get()


















