全局作用域是Laravel中为模型所有查询自动添加约束的机制,如ActiveUserScope会自动过滤status为active的用户,通过implementing Scope接口并重写apply方法实现,在模型booted中注册后生效,可用withoutGlobalScope临时移除,适用于软删除、多租户等场景,但需避免复杂逻辑以防性能问题。
在 Laravel 的 Elo
quent 模型中,全局作用域(Global Scopes)是一种为模型的所有查询自动添加约束条件的机制。它非常适合用于实现软删除、多租户系统、状态过滤等通用需求,而无需每次手动添加相同条件。
全局作用泩会在模型的每一次数据库查询中自动应用,包括 where、get、first、paginate 等方法,除非你显式地移除它。
Laravel 自带的 SoftDeletes 就是通过全局作用域实现的:自动排除被“软删除”的记录。
创建一个全局作用域需要实现 Illuminate\Database\Eloquent\Scope 接口,并定义 apply 方法。
示例:为用户模型添加“仅启用用户”作用域
第一步:创建 Scope 类
php artisan make:scope ActiveUserScope
生成的类如下:
namespace App\Scopes;use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope;
class ActiveUserScope implements Scope { public function apply(Builder $builder, Model $model) { $builder->where('status', 'active'); } }
第二步:在模型中注册全局作用域
namespace App\Models;use App\Scopes\ActiveUserScope; use Illuminate\Database\Eloquent\Model;
class User extends Model { protected static function booted() { static::addGlobalScope(new ActiveUserScope); } }
现在,所有对 User 模型的查询都会自动加上 status = 'active' 条件。
例如:
User::all(); // SELECT * FROM users WHERE status = 'active';
有时你需要获取包含非活跃用户的数据,可以使用 withoutGlobalScope 方法:
// 获取所有用户(包括非活跃) User::withoutGlobalScope(ActiveUserScope::class)->get();// 移除所有全局作用域 User::withoutGlobalScopes()->get();
// 移除特定几个作用域 User::withoutGlobalScopes([ ActiveUserScope::class, AnotherScope::class ])->get();
如果某个作用域只在特定模型中使用一次,可以直接在模型中用闭包定义:
protected static function booted()
{
static::addGlobalScope('active', function (Builder $builder) {
$builder->where('status', 'active');
});
}
移除时使用作用域名称:
User::withoutGlobalScope('active')->get();
基本上就这些。合理使用全局作用域能大幅减少重复代码,提升数据安全性与一致性。但也要注意别滥用,避免让查询行为变得“隐式”而难以追踪。