Global Scopes

最后更新于:2022-04-01 15:11:55

有时您可能希望定义一个 scope 可以用于模型的所有查询中。本质上,这也是 Eloquent 的"软删除"功能的实现原理。Global scopes 是通过 PHP traits 的组合以及实现 `Illuminate\Database\Eloquent\ScopeInterface` 接口来定义的。 首先,我们需要定义一个 trait。 这里我们用 Laravel 的 SoftDeletes 举例: ~~~ trait SoftDeletes { /** * Boot the soft deleting trait for a model. * * @return void */ public static function bootSoftDeletes() { static::addGlobalScope(new SoftDeletingScope); } } ~~~ 如果一个 Eloquent 模型引入了一个 trait ,而这个 trait 中带有符合 bootNameOfTrait 惯例命名的方法 ,那么这个方法会在 Eloquent 模型启动的时候调用, 您可以在此时注册 global scope ,或者做一些其他您想要的操作。定义的 scope 必须实现 ScopeInterface 接口,这个接口提供了两个方法:apply 和 remove。 apply 方法接受一个 Illuminate\Database\Eloquent\Builder 查询构造器对象以及它所应用的 Model,用来添加这个 scope 所需的额外的 where 子句。而remove 方法同样接受一个 Builder 对象以及 Model ,用来反向的执行 apply 操作。也就是说,remove 方法应该移除已经添加的 where 子句 (或者其他查询子句)。因此,我们的 SoftDeletingScope 的方法应该如下: ~~~ /** * Apply the scope to a given Eloquent query builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */ public function apply(Builder $builder, Model $model) { $builder->whereNull($model->getQualifiedDeletedAtColumn()); $this->extend($builder); } /** * Remove the scope from the given Eloquent query builder. * * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database\Eloquent\Model $model * @return void */ public function remove(Builder $builder, Model $model) { $column = $model->getQualifiedDeletedAtColumn(); $query = $builder->getQuery(); foreach ((array) $query->wheres as $key => $where) { // If the where clause is a soft delete date constraint, we will remove it from // the query and reset the keys on the wheres. This allows this developer to // include deleted model in a relationship result set that is lazy loaded. if ($this->isSoftDeleteConstraint($where, $column)) { unset($query->wheres[$key]); $query->wheres = array_values($query->wheres); } } } ~~~
';