Laravel模型中方法在哪里工作?

时间:2019-03-02 11:22:24

标签: laravel laravel-5 eloquent

我们经常在模型中使用where方法,但是该方法未在基​​本模型类中定义,因此laravel如何做到这一点?

例如MyModel::where('id, 2)->get();

上面的代码中肯定会获取id等于2的记录,但是这是怎么回事?我追溯到Laravel中的基本模型,但是没有找到方法在哪里!

2 个答案:

答案 0 :(得分:2)

您可以找到方法hereframework/src/Illuminate/Database/Eloquent/Builder.php

public function where($column, $operator = null, $value = null, $boolean = 'and')
    {
        if ($column instanceof Closure) {
            $column($query = $this->model->newModelQuery());
            $this->query->addNestedWhereQuery($query->getQuery(), $boolean);
        } else {
            $this->query->where(...func_get_args());
        }
        return $this;
    }

Some more info about it

答案 1 :(得分:1)

其中一些魔术存在于立面图案https://www.tutorialspoint.com/design_pattern/facade_pattern.htm

之后

但是在Laravel的情况下,他们在其Facades(\Illuminate\Support\Facades名称空间)中使用Static方法,并自动创建实例以从实例中调用这些方法,因此您无需亲自实例化Class就可以开始使用方法。例如,当您使用DB::Cache::Str::调用静态方法时。

对于Eloquent,Laravel通过将Eloquent Model配置为自动实例化模型并创建\Illuminate\Support\Facades Eloquent Builder并将这些静态方法调用转发给Eloquent Model,从而在内部更广泛地使用此方法而不将Model暴露于\Illuminate\Database\Eloquent\Builder命名空间。 Eloquent Builder实例或查询生成器实例。

模型扩展了\Illuminate\Database\Eloquent\Model,它具有一种特殊的方式,可以在运行时静态调用任何方法。

/**
 * Handle dynamic static method calls into the method.
 *
 * @param  string  $method
 * @param  array  $parameters
 * @return mixed
 */
public static function __callStatic($method, $parameters)
{
    return (new static)->$method(...$parameters);
}

因此,在某些时候,Builder将口才归类为特质

use Illuminate\Support\Traits\ForwardsCalls;

互相转发调用,以便模型可以将其静态方法转发给Eloquent构建器实例的方法。因此,如果模型没有where方法,它将把它转发到Eloquent Builder新创建实例的where方法。

从外观模式看,这是Laravel如何以静态方式从实例调用方法的方法:

// \Illuminate\Support\Facades\Facade.php
/**
 * Handle dynamic, static calls to the object.
 *
 * @param  string  $method
 * @param  array   $args
 * @return mixed
 *
 * @throws \RuntimeException
 */
public static function __callStatic($method, $args)
{
    $instance = static::getFacadeRoot();

    if (! $instance) {
        throw new RuntimeException('A facade root has not been set.');
    }

    return $instance->$method(...$args);
}

因此,调用User::where()会创建\Illuminate\Database\Eloquent\Builder的一个实例,并将方法调用转发到该实例,这是方法:

// Illuminate\Database\Eloquent\Builder.php
/**
 * Add a basic where clause to the query.
 *
 * @param  string|array|\Closure  $column
 * @param  mixed   $operator
 * @param  mixed   $value
 * @param  string  $boolean
 * @return $this
 */
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
    if ($column instanceof Closure) {
        $column($query = $this->model->newModelQuery());

        $this->query->addNestedWhereQuery($query->getQuery(), $boolean);
    } else {
        $this->query->where(...func_get_args());
    }

    return $this;
}