我正在观看Scratch系列的《 Laracasts:Laravel 5.4》,并遇到了查询范围的概念。

在视频中,我们设置了一个这样的类:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{

    public function scopeIncomplete($query)
    {

        return $query->where('completed', 0);

    }
}

我的第一个问题:

为什么这样的方法: public function scopeIncomplete($query)像这样被调用:App\Task::incomplete()::运算符?

非静态方法不是静态调用的吗?

我的第二个问题:

$query来自哪里?

据我了解,这是“现有”查询,但它的调用方式如下:App\Task::incomplete()->where('id', '>', 1)->get();
因此,我不确定该变量来自何处。

也许稍后会对其进行更深入的解释,但是我无法确定其工作原理。

最佳答案

这是非常广泛的,因为它涵盖了关于Eloquent的两个大主题。

第一种是指Eloquent使用Facade模式将静态调用传递给非静态方法的方法。

外观模式利用IoC容器将方法调用传递给类的绑定(bind)实例或新实例。

外观模式使用重载和魔术方法__callStatic。

第二个问题涉及Eloquent的重载,该重载将未注册的方法调用传递给查询构建器对象(特别是\Illuminate\Database\Eloquent\Builder)。这就是允许在Eloquent模型本身上调用where()和其他各种Query Builder方法的原因。在Model类中,您可以看到:

/**
 * Handle dynamic method calls into the model.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public function __call($method, $parameters)
{
    if (in_array($method, ['increment', 'decrement'])) {
        return $this->$method(...$parameters);
    }

    return $this->newQuery()->$method(...$parameters);
}

由于在Model中未定义where()或incomplete(),因此会将它们传递给Builder类,该类由Model::newQuery()返回。

在Builder __call方法中,您具有:
    if (method_exists($this->model, $scope = 'scope'.ucfirst($method))) {
        return $this->callScope([$this->model, $scope], $parameters);
    }

因此,这是在检查模型内部定义的范围,并传递包含此Builder实例的$ parameters。

因此,总而言之,对Model::incomplete()的调用将进行:

模型__call()->构建器__call()->模型scopeIncomplete(Builder $ builder)

关于php - 查询作用域在Laravel中如何工作?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47985413/

10-14 15:17