昨天我們追蹤到了 Query/Builder
的 where()
其實作非常的多,內容如下:
/**
* Add a basic where clause to the query.
*
* @param \Closure|string|array|\Illuminate\Contracts\Database\Query\Expression $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 ConditionExpression) {
$type = 'Expression';
$this->wheres[] = compact('type', 'column', 'boolean');
return $this;
}
// If the column is an array, we will assume it is an array of key-value pairs
// and can add them each as a where clause. We will maintain the boolean we
// received when the method was called and pass it into the nested where.
if (is_array($column)) {
return $this->addArrayOfWheres($column, $boolean);
}
// Here we will make some assumptions about the operator. If only 2 values are
// passed to the method, we will assume that the operator is an equals sign
// and keep going. Otherwise, we'll require the operator to be passed in.
[$value, $operator] = $this->prepareValueAndOperator(
$value, $operator, func_num_args() === 2
);
// If the column is actually a Closure instance, we will assume the developer
// wants to begin a nested where statement which is wrapped in parentheses.
// We will add that Closure to the query and return back out immediately.
if ($column instanceof Closure && is_null($operator)) {
return $this->whereNested($column, $boolean);
}
// If the column is a Closure instance and there is an operator value, we will
// assume the developer wants to run a subquery and then compare the result
// of that subquery with the given value that was provided to the method.
if ($this->isQueryable($column) && ! is_null($operator)) {
[$sub, $bindings] = $this->createSub($column);
return $this->addBinding($bindings, 'where')
->where(new Expression('('.$sub.')'), $operator, $value, $boolean);
}
// If the given operator is not found in the list of valid operators we will
// assume that the developer is just short-cutting the '=' operators and
// we will set the operators to '=' and set the values appropriately.
if ($this->invalidOperator($operator)) {
[$value, $operator] = [$operator, '='];
}
// If the value is a Closure, it means the developer is performing an entire
// sub-select within the query and we will need to compile the sub-select
// within the where clause to get the appropriate query record results.
if ($this->isQueryable($value)) {
return $this->whereSub($column, $operator, $value, $boolean);
}
// If the value is "null", we will just assume the developer wants to add a
// where null clause to the query. So, we will allow a short-cut here to
// that method for convenience so the developer doesn't have to check.
if (is_null($value)) {
return $this->whereNull($column, $boolean, $operator !== '=');
}
$type = 'Basic';
$columnString = ($column instanceof ExpressionContract)
? $this->grammar->getValue($column)
: $column;
// If the column is making a JSON reference we'll check to see if the value
// is a boolean. If it is, we'll add the raw boolean string as an actual
// value to the query to ensure this is properly handled by the query.
if (str_contains($columnString, '->') && is_bool($value)) {
$value = new Expression($value ? 'true' : 'false');
if (is_string($column)) {
$type = 'JsonBoolean';
}
}
if ($this->isBitwiseOperator($operator)) {
$type = 'Bitwise';
}
// Now that we are working with just a simple query we can put the elements
// in our array and add the query binding to our array of bindings that
// will be bound to each SQL statements when it is finally executed.
$this->wheres[] = compact(
'type', 'column', 'operator', 'value', 'boolean'
);
if (! $value instanceof ExpressionContract) {
$this->addBinding($this->flattenValue($value), 'where');
}
return $this;
}
我們這邊只看 "id"
"="
的場景。
if (! $value instanceof ExpressionContract) {
$this->addBinding($this->flattenValue($value), 'where');
}
return $this;
這邊在 $this->bindings
裡面加上對應的條件之後,就將自己回傳了。
接著我們就看到了 $this->whereKey($id)->first($columns)
的 first()
這部分。
/**
* Execute the query and get the first result.
*
* @param array|string $columns
* @return TValue|null
*/
public function first($columns = ['*'])
{
return $this->take(1)->get($columns)->first();
}