# 快速入門(四):連貫操作
上一篇我們?cè)敿?xì)描述了查詢語(yǔ)言的用法,但是查詢語(yǔ)言僅僅解決了查詢或者操作條件的問(wèn)題,更多的配合還需要使用模型提供的連貫操作方法。
## 介紹
連貫操作可以有效的提高數(shù)據(jù)存取的代碼清晰度和開(kāi)發(fā)效率,并且支持所有的CURD操作,也是ThinkPHP的ORM中的一個(gè)亮點(diǎn)。使用也比較簡(jiǎn)單, 假如我們現(xiàn)在要查詢一個(gè)User表的滿足狀態(tài)為1的前10條記錄,并希望按照用戶的創(chuàng)建時(shí)間排序 ,代碼如下:
~~~
$User->where('status=1')->order('create_time')->limit(10)->select();
~~~
這里的where、order和limit方法就稱之為連貫操作方法,除了select方法必須放到最后一個(gè)外(因?yàn)閟elect方法并不是連貫操作方法),連貫操作的方法調(diào)用順序沒(méi)有先后,例如,下面的代碼和上面的等效:
~~~
$User->order('create_time')->limit(10)->where('status=1')->select();
~~~
其實(shí)不僅僅是查詢方法可以使用連貫操作,包括所有的CURD方法都可以使用,例如:
~~~
$User->where('id=1')->field('id,name,email')->find();
$User->where('status=1 and id=1')->delete();
~~~
連貫操作僅在當(dāng)次查詢或者操作有效,完成后會(huì)自動(dòng)清空連貫操作的所有傳值(有個(gè)別特殊的連貫操作會(huì)記錄當(dāng)前的傳值,如cache連貫操作)。簡(jiǎn)而言之,連貫操作的結(jié)果不會(huì)帶入以后的查詢。
系統(tǒng)支持的連貫操作方法有:
|方法 |作用 |支持的參數(shù)類型|
|-------|--------|-------------|
|where* |用于查詢或者更新條件的定義 |字符串、數(shù)組和對(duì)象|
|table |用于定義要操作的數(shù)據(jù)表名稱 |字符串和數(shù)組|
|alias |用于給當(dāng)前數(shù)據(jù)表定義別名 |字符串|
|data |用于新增或者更新數(shù)據(jù)之前的數(shù)據(jù)對(duì)象賦值 |數(shù)組和對(duì)象|
|field |用于定義要查詢的字段(支持字段排除) |字符串和數(shù)組|
|order |用于對(duì)結(jié)果排序 |字符串和數(shù)組|
|limit |用于限制查詢結(jié)果數(shù)量 |字符串和數(shù)字|
|page |用于查詢分頁(yè)(內(nèi)部會(huì)轉(zhuǎn)換成limit) |字符串和數(shù)字|
|group |用于對(duì)查詢的group支持 |字符串|
|having |用于對(duì)查詢的having支持 |字符串|
|join* |用于對(duì)查詢的join支持 |字符串和數(shù)組|
|union* |用于對(duì)查詢的union支持 |字符串、數(shù)組和對(duì)象|
|distinct |用于查詢的distinct支持 |布爾值|
|lock |用于數(shù)據(jù)庫(kù)的鎖機(jī)制 |布爾值|
|cache |用于查詢緩存 |支持多個(gè)參數(shù)(以后在緩存部分再詳細(xì)描述)|
|relation |用于關(guān)聯(lián)查詢(需要關(guān)聯(lián)模型擴(kuò)展支持) |字符串|
|validate |用于數(shù)據(jù)自動(dòng)驗(yàn)證 |數(shù)組|
|auto |用于數(shù)據(jù)自動(dòng)完成 |數(shù)組|
|filter |用于數(shù)據(jù)過(guò)濾 |字符串|
|scope* |用于命名范圍 |字符串、數(shù)組|
|bind* |用于數(shù)據(jù)綁定操作 |數(shù)組或多個(gè)參數(shù)|
|token |用于令牌驗(yàn)證 |布爾值|
|comment |用于SQL注釋 |字符串|
|index |用于數(shù)據(jù)集的強(qiáng)制索引| 字符串|
|strict |用于數(shù)據(jù)入庫(kù)的嚴(yán)格檢測(cè)| 布爾值|
所有的連貫操作都返回當(dāng)前的模型實(shí)例對(duì)象,其中帶*標(biāo)識(shí)的表示支持多次調(diào)用。
## 用法
由于連貫操作的使用往往涉及到多個(gè)方法的聯(lián)合使用,下面大概介紹下各個(gè)連貫操作的基本用法:
#### WHERE
|where |用于查詢或者更新條件的定義|
|-------|-------------------------|
|用法 |where($where)|
|參數(shù) |where(必須):查詢或者操作條件,支持字符串、數(shù)組和對(duì)象|
|返回值 |當(dāng)前模型實(shí)例|
> 備注 如果不調(diào)用where方法,默認(rèn)不會(huì)執(zhí)行更新和刪除操作
Where方法是使用最多的連貫操作方法,更詳細(xì)的用法請(qǐng)參考:[快速入門(3)查詢語(yǔ)言](query)。
### TABLE
|table |定義要操作的數(shù)據(jù)表名稱,動(dòng)態(tài)改變當(dāng)前操作的數(shù)據(jù)表名稱,需要寫數(shù)據(jù)表的全名,包含前綴,可以使用別名和跨庫(kù)操作|
|-------|-------------------------|
|用法 |table($table)|
|參數(shù) |table(必須):數(shù)據(jù)表名稱,支持操作多個(gè)表,支持字符串、數(shù)組和對(duì)象|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:如果不調(diào)用table方法,會(huì)自動(dòng)獲取模型對(duì)應(yīng)或者定義的數(shù)據(jù)表
用法示例:
~~~
$Model->Table('think_user user')->where('status>1')->select();
~~~
也可以在table方法中跨庫(kù)操作,例如:
~~~
$Model->Table('db_name.think_user user')->where('status>1')->select();
~~~
Table方法的參數(shù)支持字符串和數(shù)組,數(shù)組方式的用法:
~~~
$Model->Table(array('think_user'=>'user','think_group'=>'group'))->where('status>1')->select();
~~~
使用數(shù)組方式定義的優(yōu)勢(shì)是可以避免因?yàn)楸砻完P(guān)鍵字沖突而出錯(cuò)的情況。
一般情況下,無(wú)需調(diào)用table方法,默認(rèn)會(huì)自動(dòng)獲取當(dāng)前模型對(duì)應(yīng)或者定義的數(shù)據(jù)表。
### DATA
|data |可以用于新增或者保存數(shù)據(jù)之前的數(shù)據(jù)對(duì)象賦值|
|-------|-------------------------|
|用法 |data($data)|
|參數(shù) |data(必須):數(shù)據(jù),支持?jǐn)?shù)組和對(duì)象|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:如果不調(diào)用data方法,則會(huì)取當(dāng)前的數(shù)據(jù)對(duì)象或者傳入add和save的數(shù)據(jù)
使用示例:
~~~
$Model->data($data)->add();
$Model->data($data)->where('id=3')->save();
~~~
Data方法的參數(shù)支持對(duì)象和數(shù)組,如果是對(duì)象會(huì)自動(dòng)轉(zhuǎn)換成數(shù)組。如果不定義data方法賦值,也可以使用create方法或者手動(dòng)給數(shù)據(jù)對(duì)象賦值的方式。
模型的data方法除了創(chuàng)建數(shù)據(jù)對(duì)象之外,還可以讀取當(dāng)前的數(shù)據(jù)對(duì)象,
例如:
~~~
$this->find(3);
$data = $this->data();
~~~
### FIELD
|field |用于定義要查詢的字段|
|-------|-------------------------|
|用法 |field($field,$except=false)|
|參數(shù) |field(必須):字段名,支持字符串和數(shù)組,支持指定字段別名;如果為true則表示顯式或者數(shù)據(jù)表的所有字段。except(可選):是否排除,默認(rèn)為false,如果為true表示定義的字段為數(shù)據(jù)表中排除field參數(shù)定義之外的所有字段。|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:如果不調(diào)用field方法,則默認(rèn)返回所有字段,和field('*')等效
使用示例:
~~~
$Model->field('id,nickname as name')->select();
$Model->field(array('id','nickname'=>'name'))->select();
~~~
如果不調(diào)用field方法或者field方法傳入?yún)?shù)為空的話,和使用field('*')是等效的。
如果需要顯式的傳入所有的字段,可以使用下面的方法:
~~~
$Model->field(true)->select();
~~~
但是我們更建議只獲取需要顯式的字段名,或者采用字段排除方式來(lái)定義,例如:
~~~
$Model->field('status',true)->select();
~~~
表示獲取除了status之外的所有字段。
### ORDER
|order |用于對(duì)操作結(jié)果排序|
|-------|-------------------------|
|用法 |order($order)|
|參數(shù) |order(必須):排序的字段名,支持字符串和數(shù)組,支持多個(gè)字段排序|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:如果不調(diào)用order方法,按照數(shù)據(jù)庫(kù)的默認(rèn)規(guī)則
使用示例:
~~~
order('id desc')
~~~
排序方法支持對(duì)多個(gè)字段的排序
~~~
order('status desc,id asc')
~~~
order方法的參數(shù)支持字符串和數(shù)組,數(shù)組的用法如下:
~~~
order(array('status'=>'desc','id'))
~~~
### LIMIT
|limit |用于定義要查詢的結(jié)果限制(支持所有的數(shù)據(jù)庫(kù)類型)|
|-------|-------------------------|
|用法 |limit($limit)|
|參數(shù) |limit(必須):限制數(shù)量,支持字符串|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:如果不調(diào)用limit方法,則表示沒(méi)有限制
我們知道不同的數(shù)據(jù)庫(kù)類型的limit用法是不盡相同的,但是在ThinkPHP的用法里面始終是統(tǒng)一的方法,也就是limit('offset,length') ,無(wú)論是Mysql、SqlServer還是Oracle數(shù)據(jù)庫(kù),都是這樣使用,系統(tǒng)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)類會(huì)負(fù)責(zé)解決這個(gè)差異化。
使用示例:
~~~
limit('1,10')
~~~
也可以用下面的兩個(gè)參數(shù)的寫法,是等效的:
~~~
limit(1,10)
如果使用
limit('10')
等效于
limit('0,10')
~~~
### PAGE
|page |用于定義要查詢的數(shù)據(jù)分頁(yè)|
|-------|-------------------------|
|用法 |page($page)|
|參數(shù) |page(必須):分頁(yè),支持字符串|
|返回值 |當(dāng)前模型實(shí)例|
Page操作方法可以更加快速的進(jìn)行分頁(yè)查詢。
Page方法的用法和limit方法類似,格式為:
~~~
Page('page[,listRows]')
~~~
Page表示當(dāng)前的頁(yè)數(shù),listRows表示每頁(yè)顯示的記錄數(shù)。例如:
~~~
Page('2,10')
~~~
表示每頁(yè)顯示10條記錄的情況下面,獲取第2頁(yè)的數(shù)據(jù)。
listRow如果不寫的話,會(huì)讀取limit('length') 的值,例如:
~~~
limit(25)->page(3);
~~~
表示每頁(yè)顯示25條記錄的情況下面,獲取第3頁(yè)的數(shù)據(jù)。
如果limit也沒(méi)有設(shè)置的話,則默認(rèn)為每頁(yè)顯示20條記錄。
page方法也支持傳入二個(gè)參數(shù),例如:
~~~
$this->page(5,25)->select();
~~~
和之前的用法
~~~
$this->page('5,25')->select();
~~~
等效。
### GROUP
|group |用于數(shù)據(jù)庫(kù)的group查詢支持|
|-------|-------------------------|
|用法 |group($group)|
|參數(shù) |group(必須):group的字段名,支持字符串|
|返回值 |當(dāng)前模型實(shí)例|
使用示例:
~~~
group('user_id')
~~~
> Group方法的參數(shù)只支持字符串
### HAVING
|having |用于數(shù)據(jù)庫(kù)的having查詢支持|
|-------|-------------------------|
|用法 |having($having)|
|參數(shù) |having(必須):having,支持字符串|
|返回值 |當(dāng)前模型實(shí)例|
使用示例:
~~~
having('user_id>0')
~~~
> having方法的參數(shù)只支持字符串
### JOIN
|join |用于數(shù)據(jù)庫(kù)的join查詢支持|
|-------|-------------------------|
|用法 |join($join)|
|參數(shù) |join(必須):join操作,支持字符串和數(shù)組|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:join方法支持多次調(diào)用
使用示例:
~~~
$Model->join(' work ON artist.id = work.artist_id')->join('card ON artist.card_id = card.id')->select();
~~~
默認(rèn)采用JOIN (等同于 INNER JOIN)方式,如果需要用其他的JOIN方式,可以改成
~~~
$Model->join('RIGHT JOIN work ON artist.id = work.artist_id')->select();
~~~
如果join方法的參數(shù)用數(shù)組的話,只能使用一次join方法,并且不能和字符串方式混合使用。
例如:
~~~
join(array(' work ON artist.id = work.artist_id','card ON artist.card_id = card.id'))
~~~
### UNION
|union |用于數(shù)據(jù)庫(kù)的union查詢支持|
|-------|-------------------------|
|用法 |union($union,$all=false)|
|參數(shù) |union(必須):union操作,支持字符串、數(shù)組和對(duì)象 all(可選):是否采用UNION ALL 操作,默認(rèn)為false|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:Union方法支持多次調(diào)用
使用示例:
~~~
$Model->field('name')
->table('think_user_0')
->union('SELECT name FROM think_user_1')
->union('SELECT name FROM think_user_2')
->select();
~~~
數(shù)組用法:
~~~
$Model->field('name')
->table('think_user_0')
->union(array('field'=>'name','table'=>'think_user_1'))
->union(array('field'=>'name','table'=>'think_user_2'))
->select();
~~~
或者
~~~
$Model->field('name')
->table('think_user_0')
->union(array('SELECT name FROM think_user_1','SELECT name FROM think_user_2'))
->select();
~~~
支持UNION ALL 操作,例如:
~~~
$Model->field('name')
->table('think_user_0')
->union('SELECT name FROM think_user_1',true)
->union('SELECT name FROM think_user_2',true)
->select();
~~~
或者
~~~
$Model->field('name')
->table('think_user_0')
->union(array('SELECT name FROM think_user_1','SELECT name FROM think_user_2'),true)
->select();
~~~
每個(gè)union方法相當(dāng)于一個(gè)獨(dú)立的SELECT語(yǔ)句。
> 注意:UNION 內(nèi)部的 SELECT 語(yǔ)句必須擁有相同數(shù)量的列。列也必須擁有相似的數(shù)據(jù)類型。同時(shí),每條 SELECT 語(yǔ)句中的列的順序必須相同。
### DISTINCT
|distinct |查詢數(shù)據(jù)的時(shí)候進(jìn)行唯一過(guò)濾|
|-------|-------------------------|
|用法 |distinct($distinct)|
|參數(shù) |distinct(必須):是否采用distinct,支持布爾值|
|返回值 |當(dāng)前模型實(shí)例|
使用示例:
~~~
$Model->Distinct(true)->field('name')->select();
~~~
### LOCK
|lock |用于查詢或者寫入鎖定|
|-------|-------------------------|
|用法 |lock($lock)|
|參數(shù) |lock(必須):是否需要鎖定,支持布爾值|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:join方法支持多次調(diào)用
Lock方法是用于數(shù)據(jù)庫(kù)的鎖機(jī)制,如果在查詢或者執(zhí)行操作的時(shí)候使用:
~~~
lock(true)
~~~
就會(huì)自動(dòng)在生成的SQL語(yǔ)句最后加上 FOR UPDATE或者FOR UPDATE NOWAIT(Oracle數(shù)據(jù)庫(kù))。
### VALIDATE
|validate |用于數(shù)據(jù)的自動(dòng)驗(yàn)證|
|-------|-------------------------|
|用法 |validate($validate)|
|參數(shù) |validate(必須):自動(dòng)驗(yàn)證定義|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:只能和create方法配合使用
validate方法用于數(shù)據(jù)的自動(dòng)驗(yàn)證,我們會(huì)在數(shù)據(jù)驗(yàn)證部分詳細(xì)描述。
### AUTO
|auto |用于數(shù)據(jù)自動(dòng)完成|
|-------|-------------------------|
|用法 |auto($auto)|
|參數(shù) |auto(必須):定義自動(dòng)完成|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:auto方法只能配合create方法使用
auto方法用于數(shù)據(jù)的自動(dòng)完成操作,具體使用我們會(huì)在數(shù)據(jù)自動(dòng)完成部分描述。
### SCOPE
|scope |用于模型的命名范圍|
|-------|-------------------------|
|用法 |scope($scope)|
|參數(shù) |scope(必須):命名范圍定義|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:scope方法其實(shí)是連貫操作的預(yù)定義
scope方法的具體用法可以參考:3.1的新特性 命名范圍
### FILTER
|filter |用于數(shù)據(jù)的安全過(guò)濾|
|-------|-------------------------|
|用法 |filter($filter)|
|參數(shù) |filter(必須):過(guò)濾方法名|
|返回值 |當(dāng)前模型實(shí)例|
> 備注:filter方法一般用于寫入和更新操作
filter方法用于對(duì)數(shù)據(jù)對(duì)象的安全過(guò)濾,例如:
~~~
$Model->data($data)->filter('strip_tags')->add();
~~~
目前filter方法不支持多個(gè)方法的過(guò)濾。
## 總結(jié)
連貫操作為我們的數(shù)據(jù)操作帶來(lái)了很大的便捷之處,并且只要SQL可以實(shí)現(xiàn)的操作,基本上都可以用ThinkPHP的連貫操作來(lái)實(shí)現(xiàn),并且不用考慮數(shù)據(jù)庫(kù)之間的表達(dá)差異,具有可移植性。后面會(huì)和大家講解如何操作和獲取變量。
- 快速入門 1:基礎(chǔ)
- 快速入門 2:CURD
- 快速入門 3:查詢語(yǔ)言
- 快速入門 4:連貫操作
- 快速入門 5:變量
- 快速入門 6:路由
- 快速入門 7:視圖
- 快速入門 8:變量輸出
- 快速入門 9:循環(huán)和控制輸出
- 快速入門 10:公共模板和模板布局
- 快速入門 11:Action參數(shù)綁定
- 快速入門 12:空操作和空控制器
- 快速入門 13:初始化、前置和后置操作
- 快速入門 14:頁(yè)面跳轉(zhuǎn)和重定向
- 快速入門 15:頁(yè)面請(qǐng)求和AJAX
- 快速入門 16:偽靜態(tài)
- 快速入門 17:操作綁定到類
- 快速入門 18:多層控制器
- 快速入門 19:自動(dòng)驗(yàn)證
- 快速入門 20:自動(dòng)完成
