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