
通过定义全局作用域(Global Scopes),可让 Laravel 在每次查询该模型时自动追加 WHERE status = 1 等条件,无需重复书写,实现类似软删除的透明过滤机制。
通过定义全局作用域(global scopes),可让 laravel 在每次查询该模型时自动追加 `where status = 1` 等条件,无需重复书写,实现类似软删除的透明过滤机制。
在 Laravel 中,若需对某个模型的所有查询默认强制过滤(如仅允许 status = 1 的活跃记录),应使用 全局作用域(Global Scopes) —— 这是 Laravel 官方推荐的、用于实现“自动 WHERE 条件”的标准方案,其原理与 SoftDeletes trait 完全一致。
✅ 正确实现方式:注册全局作用域
-
创建作用域类(推荐,更清晰可维护):
// 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); } }
2. **在模型中注册全局作用域**:
```php
// 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(); // 等价于 SELECT * FROM models WHERE status = 1 LIMIT 1
Model::where('name', 'test')->get(); // 等价于 SELECT * FROM models WHERE status = 1 AND name = 'test'
Model::withTrashed()->get(); // ❌ 不受影响(除非显式移除作用域)⚠️ 注意事项
- 全局作用域默认不可绕过;如需临时禁用(例如后台管理查看全部状态),可使用:
Model::withoutGlobalScopes()->get(); // 移除所有全局作用域 Model::withoutGlobalScope(ActiveScope::class)->get(); // 仅移除指定作用域
- 若模型已存在大量业务逻辑依赖未加 status 的查询,请务必充分测试,避免意外数据遗漏;
- 避免在作用域中使用闭包(static::addGlobalScope('active', function () { ... })),因其无法被 withoutGlobalScope() 精确移除,推荐使用类形式。
? 扩展建议
如需支持多环境状态(如 status IN (1, 2))、或动态值(如租户 ID),可在作用域中结合 app()->environment() 或 Auth::id() 等上下文灵活构造条件,但需注意避免 N+1 或会话泄漏风险。
全局作用域是 Laravel 实现数据访问层统一约束的核心机制——正确使用它,既能提升代码健壮性,又能显著降低人为疏漏风险。











