为什么`method_exists($ scope,' extend')存在于Laravel的Buidler方法`withGlobalScope`中

时间:2017-02-14 14:20:12

标签: php laravel laravel-5 laravel-5.3

当我阅读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);
}

谢谢!

1 个答案:

答案 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(),
        ]);
    });
}