当我阅读Laravel 5.3的源代码时,我发现以下代码
public function withGlobalScope($identifier, $scope)
{
$this->scopes[$identifier] = $scope;
if (method_exists($scope, 'extend')) {
$scope->extend($this);
}
return $this;
}
我很困惑为什么它在方法中是以下代码,是否在任何地方使用?
if (method_exists($scope, 'extend')) {
$scope->extend($this);
}
谢谢!
答案 0 :(得分:1)
它意味着在Scope类的上下文中扩展Builder。
在全局Scope(扩展Scope接口的类)中,您可以在apply函数旁边创建一个扩展函数。
使用Eloquent构建器作为参数调用此扩展函数。想象一下一些PopularUsersScope,它只会得到非常受欢迎的用户:
public function apply(Builder $builder, Model $model): void
{
$builder->join(...)->where(...) // determine popularity
}
public function extend(Builder $builder)
{
$builder->macro('demote', function (Builder $builder) {
return $builder->update(...) // query to make user not so popular
});
}
现在让我们有一个模型Clan,它是一组用户,其中一些很受欢迎。我们对Clan有一个约束关系:
public function popular_users(): belongsToMany
{
return $this->hasMany(User::class)
->withGlobalScope('popularUsers', new PopularUsersScope)
}
因为我们在范围扩展功能中定义了一个宏,所以我们可以为任何热门用户$user->demote()
,但不能为普通用户做。{/ p>
这可能是一个愚蠢的例子,但它在相当抽象的用例中很有用。
请参阅Laravel框架代码中的SoftDeletingScope以获取实际示例:SoftDeletable项目需要在Builder上使用一些额外的方法来恢复和急切加载已删除的项目。
SoftDeletingScope中的Extend从数组$this->extensions
动态地向Builder添加多个扩展,并在模型上注册默认删除功能的替换:
public function extend(Builder $builder)
{
foreach ($this->extensions as $extension) {
$this->{"add{$extension}"}($builder);
}
$builder->onDelete(function (Builder $builder) {
$column = $this->getDeletedAtColumn($builder);
return $builder->update([
$column => $builder->getModel()->freshTimestampString(),
]);
});
}