Builder::where
源碼
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
if (is_array($column)) {
return $this->whereNested(function ($query) use ($column) {
foreach ($column as $key => $value) {
$query->where($key, '=', $value);
}
}, $boolean);
}
if (func_num_args() == 2) {
list($value, $operator) = [$operator, '='];
} elseif ($this->invalidOperatorAndValue($operator, $value)) {
throw new InvalidArgumentException('Illegal operator and value combination.');
}
if ($column instanceof Closure) {
return $this->whereNested($column, $boolean);
}
if (! in_array(strtolower($operator), $this->operators, true)) {
list($value, $operator) = [$operator, '='];
}
if ($value instanceof Closure) {
return $this->whereSub($column, $operator, $value, $boolean);
}
if (is_null($value)) {
return $this->whereNull($column, $boolean, $operator != '=');
}
$type = 'Basic';
$this->wheres[] = compact('type', 'column', 'operator', 'value', 'boolean');
if (! $value instanceof Expression) {
$this->addBinding($value, 'where');
}
return $this;
}
解讀
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
//如果參數(shù)column是一個(gè)數(shù)組赴涵,將假設(shè)這個(gè)數(shù)組是一個(gè)“字段”-“值”對應(yīng)的關(guān)系對
//并且默認(rèn)這些查詢條件是并列存在的關(guān)系刨肃,即需滿足所有的where數(shù)組贸典,參見示例1
//如果傳遞了兩個(gè)參數(shù),將假設(shè)$popertor為“=”演训,否則將會(huì)拋出一個(gè)異常允悦,參見示例2
//如果$column是一個(gè)閉包,暫時(shí)不能理解如果是一個(gè)閉包會(huì)發(fā)生什么莲趣,只知道允許$column是一個(gè)閉包鸳慈。o(╯□╰)o
//參數(shù)$operator有一個(gè)允許的范圍,如果不在允許范圍之內(nèi)喧伞,則默認(rèn)$operator為“=”走芋,參見示例4
//如果第三個(gè)參數(shù)$value是一個(gè)閉包,同$column閉包潘鲫,不能理解...翁逞,參見示例3
//如果$value是空的
}
示例1
User::where([
"name" => "Zoe",
"gender" => "male"
], null, null, "or") -> get();
不管后面的三個(gè)參數(shù)如何變,最終的sql都是:“select * from `usr_userinfo` where (`id` = ? and `nickname` = ?)”溉仑。
示例2
User::where("id", "4")->...
等于User::where("id", "=", 4)->...
示例3
User::where("foo", "=", function($query){
$query -> from((new CmsUser()) -> getTable()) -> where("fiz", "biz");
}) -> toSql();
//select * from `usr_userinfo` where `foo` = (select * from `cms_user` where `fiz` = ?)
示例4
允許的operator參數(shù)
'=', '<', '>', '<=', '>=', '<>', '!=',
'like', 'like binary', 'not like', 'between', 'ilike',
'&', '|', '^', '<<', '>>',
'rlike', 'regexp', 'not regexp',
'~', '~*', '!~', '!~*', 'similar to',
'not similar to'
啟示
一般是通過模型調(diào)用靜態(tài)方法where
去實(shí)現(xiàn)查詢挖函,但在model
里面并沒有where
這一個(gè)方法,可以清楚的是浊竟,最終是通過調(diào)用builder::where
來實(shí)現(xiàn)最終的查詢怨喘。那么,在model
里面是怎么找到builder::where
的呢振定?
在Eloquent::model
下面看到了如下代碼:
public function __call($method, $parameters)
{
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
$query = $this->newQuery();
return call_user_func_array([$query, $method], $parameters);
}
public static function __callStatic($method, $parameters)
{
$instance = new static;
return call_user_func_array([$instance, $method], $parameters);
}
通過__call
和__callStatic
這兩個(gè)魔術(shù)方法實(shí)現(xiàn)了對不可訪問的方法的訪問(another time, I will note them)必怜。
在builder
里面,laravel
對函數(shù)功能進(jìn)行了特別細(xì)致和合理的劃分后频,比如對builder
類中屬性$binding
的操作梳庆。首先有一個(gè)設(shè)置$binding
的函數(shù)setBindings(array $bindings, $type = "where")
,對$this->binding
進(jìn)行初始化。與之相對的靠益,builder
還提供了獲取$this->builder
的函數(shù)getBindings()
和getRawBindings()(暫時(shí)不能區(qū)分兩者)
丧肴。然后提供了對$this->binding
的添加操作addBinding($value, $type = "where")
,和mergeBindings(Builder $query)
胧后。
這些函數(shù)其實(shí)就是針對屬性$this->binding
的增刪改查芋浮,對$this->binding
生命周期的控制(參見vue2.0
的生命周期)。一個(gè)優(yōu)秀的程序無非就是由這些“元”操作組成壳快,在語言層面纸巷,各種語言已經(jīng)為我們封裝了一層。寫程序眶痰,就是在程序?qū)用媪鲋迹槍Σ煌臉I(yè)務(wù),將整個(gè)流程分解成一個(gè)個(gè)不可細(xì)分竖伯、可以重復(fù)使用的“元”模塊存哲,一個(gè)個(gè)“元”類,一個(gè)個(gè)“元”函數(shù)七婴。
對于流程祟偷,我們會(huì)不斷的重復(fù),因?yàn)闃I(yè)務(wù)不可能只是針對單人或者單次打厘。我們就像拼積木一樣對整個(gè)過程進(jìn)行拆解修肠,在類和函數(shù)的內(nèi)部,我們不能信任任何輸入户盯,我們需要在每一個(gè)“元”保持輸入的可靠性嵌施,這大概就是“低內(nèi)聚、高耦合”了吧莽鸭。對輸入進(jìn)行檢查吗伤,檢查類型和值,只有得到符合要求的數(shù)據(jù)時(shí)才能進(jìn)行下一步功能操作蒋川,輸出時(shí)也要對數(shù)據(jù)進(jìn)行過濾牲芋,給對方想要的數(shù)據(jù),只給對方想要的數(shù)據(jù)捺球。
而流程針對用戶,則體現(xiàn)為我做了什么夕冲、我要做什么际歼、我沒有做什么蒲列、我應(yīng)該怎么做、做完之后我該怎么辦、如果我沒做又會(huì)怎么樣慨畸。比如今天Boss讓我做一個(gè)針對案件的通知管理倘屹,因?yàn)檫@個(gè)通知不是“我”發(fā)出去的,也無法修改,更不可以刪除掺涛,所以從增刪改查的角度,我只是對通知做了一個(gè)顯示疼进,完全沒有考慮到如果通知沒法出去怎么辦薪缆?應(yīng)該在哪些步驟發(fā)通知,發(fā)了還是沒發(fā)伞广?沒發(fā)要怎么發(fā)拣帽?說來也是奇怪,Boss最近好像心情比較好嚼锄,之前拿一些比較棘手的問題去資訊他减拭,他都會(huì)不是很耐煩,今天我完全沒搞懂應(yīng)該怎么寫区丑,他還耐心的給我解釋了好久拧粪,很奇怪。大概是因?yàn)榱鞒毯苤匾伞?/p>
vue2.0生命周期
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
activated
deactivated
beforeDestroy
destroyed