上一篇写到Eloquent ORM的基类Builder类,这次就来看一下这些方便的ORM方法是如何转换成sql语句运行的。
首先还是进入\vendor\laravel\framework\src\Illuminate\Database\Query\Builder.php这个类中,先来看一下最常用的where()方法。
如下所示,where方法的代码很长,但前面多个if都是用来兼容各种不同调用式的。我们先抛开这些花哨的调用方式,来看一下最简单的调用方法是怎么运行的。
1 /** 2 * Add a basic where clause to the query. 3 * 4 * @param string|array|\Closure $column 5 * @param mixed $operator 6 * @param mixed $value 7 * @param string $boolean 8 * @return $this 9 */ 10 public function where($column, $operator = null, $value = null, $boolean = 'and') 11 { 12 // If the column is an array, we will assume it is an array of key-value pairs 13 // and can add them each as a where clause. We will maintain the boolean we 14 // received when the method was called and pass it into the nested where. 15 if (is_array($column)) { 16 return $this->addArrayOfWheres($column, $boolean); 17 } 18 19 // Here we will make some assumptions about the operator. If only 2 values are 20 // passed to the method, we will assume that the operator is an equals sign 21 // and keep going. Otherwise, we'll require the operator to be passed in. 22 list($value, $operator) = $this->prepareva lueAndOperator( 23 $value, $operator, func_num_args() == 2 24 ); 25 26 // If the columns is actually a Closure instance, we will assume the developer 27 // wants to begin a nested where statement which is wrapped in parenthesis. 28 // We'll add that Closure to the query then return back out immediately. 29 if ($column instanceof Closure) { 30 return $this->whereNested($column, $boolean); 31 } 32 33 // If the given operator is not found in the list of valid operators we will 34 // assume that the developer is just short-cutting the '=' operators and 35 // we will set the operators to '=' and set the values appropriately. 36 if ($this->invalidOperator($operator)) { 37 list($value, $operator) = [$operator, '=']; 38 } 39 40 // If the value is a Closure, it means the developer is performing an entire 41 // sub-select within the query and we will need to compile the sub-select 42 // within the where clause to get the appropriate query record results. 43 if ($value instanceof Closure) { 44 return $this->whereSub($column, $operator, $value, $boolean); 45 } 46 47 // If the value is "null", we will just assume the developer wants to add a 48 // where null clause to the query. So, we will allow a short-cut here to 49 // that method for convenience so the developer doesn't have to check. 50 if (is_null($value)) { 51 return $this->whereNull($column, $boolean, $operator !== '='); 52 } 53 54 // If the column is making a JSON reference we'll check to see if the value 55 // is a boolean. If it is, we'll add the raw boolean string as an actual 56 // value to the query to ensure this is properly handled by the query. 57 if (Str::contains($column, '->') && is_bool($value)) { 58 $value = new Expression($value ? 'true' : 'false'); 59 } 60 61 // Now that we are working with just a simple query we can put the elements 62 // in our array and add the query binding to our array of bindings that 63 // will be bound to each SQL statements when it is finally executed. 64 $type = 'Basic'; 65 66 $this->wheres[] = compact( 67 'type', 'column', 'operator', 'value', 'boolean' 68 ); 69 70 if (! $value instanceof Expression) { 71 $this->addBinding($value, 'where'); 72 } 73 74 return $this; 75 }
先从这个方法的参数开始,它一