
通过定义全局作用域(Global Scope),可让指定模型的所有 Eloquent 查询自动附加 where 条件(如 where('status', 1)),无需每次手动调用,效果类似 SoftDeletes 的 deleted_at IS NULL 过滤。
通过定义全局作用域(global scope),可让指定模型的所有 eloquent 查询自动附加 where 条件(如 where('status', 1)),无需每次手动调用,效果类似 softdeletes 的 deleted_at is null 过滤。
在 Laravel 中,实现“自动添加 where 条件”的标准方案是使用 全局查询作用域(Global Query Scopes) —— 它会在模型的每一个查询构建过程中自动注入约束逻辑,确保数据一致性与开发效率。
✅ 正确实现方式:注册全局作用域
首先,创建一个全局作用域类(推荐放在 app/Scopes 目录下):
// app/Scopes/ActiveScope.php
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('status', 1);
}
}然后,在目标模型中注册该作用域(通常在 booted() 方法中):
// app/Models/Model.php
<?php
namespace App\Models;
use App\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Model;
class Model extends Model
{
protected static function booted()
{
static::addGlobalScope(new ActiveScope());
}
}✅ 完成后,所有查询将自动生效:
Model::first(); // 等价于 WHERE status = 1
Model::where('name', 'John')->get(); // 等价于 WHERE status = 1 AND name = 'John'
Model::with('user')->find(5); // 同样受约束⚠️ 注意事项
-
排除全局作用域:若某次查询需绕过该限制(例如后台管理查看全部状态),使用 withoutGlobalScopes() 或 withoutGlobalScope(ActiveScope::class):
Model::withoutGlobalScopes()->get(); // 忽略所有全局作用域 Model::withoutGlobalScope(ActiveScope::class)->get(); // 仅忽略 ActiveScope
作用域顺序与组合:多个全局作用域按注册顺序依次应用;避免在 apply() 中执行复杂逻辑或数据库操作(应保持轻量、无副作用)。
与软删除共存:全局作用域与 SoftDeletes 可同时存在,Laravel 会合并所有约束(如 WHERE status = 1 AND deleted_at IS NULL)。
? 小结
全局作用域是 Laravel 提供的优雅机制,专为解决“重复过滤条件”这类横切关注点而设计。相比反复手写 where('status', 1),它提升了代码可维护性、降低了遗漏风险,并保持了 Eloquent 查询链的简洁性。建议将业务中通用的状态过滤(如 active, published, approved)统一抽象为命名清晰的全局作用域,形成团队共识的查询规范。


















