我们经常在模型中使用where
方法,但是该方法未在基本模型类中定义,因此laravel如何做到这一点?
例如MyModel::where('id, 2)->get();
上面的代码中肯定会获取id等于2的记录,但是这是怎么回事?我追溯到Laravel中的基本模型,但是没有找到方法在哪里!
答案 0 :(得分:2)
您可以找到方法here。 framework/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;
}
答案 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;
}