上一節(jié)寫了關(guān)于TP的一些概念,這一節(jié)主要記錄對數(shù)據(jù)庫的CURD操作。
看完官方文檔頓時感覺TP對數(shù)據(jù)操作API的封裝是如此的強(qiáng)大绒极,對于查詢語句這一參數(shù)就支持數(shù)組、字符串蔬捷、對象這三種方式垄提。
數(shù)據(jù)庫的操作是由模型來管理的榔袋,首先先談一談模型相關(guān)。
模型
模型類的作用大多數(shù)情況是操作數(shù)據(jù)表的铡俐,如果按照系統(tǒng)的規(guī)范來命名模型類的話凰兑,大多數(shù)情況下是可以用模型的名字自動對應(yīng)數(shù)據(jù)表的。
模型類的命名規(guī)則是除去表前綴的數(shù)據(jù)表名稱审丘,采用駝峰法命名吏够,并且首字母大寫,然后加上模型層的名稱(默認(rèn)定義是Model)滩报,例如:
模型名 | 約定對應(yīng)數(shù)據(jù)表(假設(shè)數(shù)據(jù)庫的前綴定義是 think_) |
---|---|
UserModel | think_user |
UserTypeModel | think_user_type |
如果你的規(guī)則和上面的系統(tǒng)約定不符合锅知,那么需要設(shè)置Model類對應(yīng)的數(shù)據(jù)表名稱,可以通過模型對象調(diào)用table方法指定數(shù)據(jù)庫表名脓钾,以確保能夠找到對應(yīng)的數(shù)據(jù)表售睹。
1.TP是通過數(shù)據(jù)模型實例化對象來操作對應(yīng)的數(shù)據(jù)表的,對于模型類并非必須要創(chuàng)建對應(yīng)的類可训,只有當(dāng)存在獨立的業(yè)務(wù)邏輯或者屬性的時候才需要定義昌妹。
2.正如控制器類一樣,所有的的模型類都繼承自TP的Model或其子類沉噩。
3.對于模型類這一塊你可以大致的看一下就行捺宗,實戰(zhàn)的時候你會發(fā)現(xiàn)你基本上不用去創(chuàng)建模型類,直接用M函數(shù)就搞定了.
直接實例化(請忽略我 o(╯□╰)o )
可以和實例化其他類庫一樣實例化模型類川蒙,例如:
$User = new \Home\Model\UserModel();
$Info = new \Admin\Model\InfoModel();
// 帶參數(shù)實例化
$New = new \Home\Model\NewModel('blog','think_',$connection)
快速實例化(著重看)
TP提供了快捷實例化模型的API蚜厉,上面的直接實例化的時候我們需要傳入完整的類名,系統(tǒng)提供了一個快捷方法D用于數(shù)據(jù)模型的實例化操作畜眨。
要實例化自定義模型類昼牛,可以使用下面的方式:
M方法
<a>M('[基礎(chǔ)模型名:]模型名',['數(shù)據(jù)表前綴'],['數(shù)據(jù)庫連接信息'])
一般我們只需要傳第一個參數(shù),后兩個參數(shù)基本上不寫康聂,因為我們會在配置文件中寫
</a>
D方法實例化模型類的時候通常是實例化某個具體的模型類贰健,如果你僅僅是對數(shù)據(jù)表進(jìn)行基本的CURD操作的話,使用M方法實例化的話恬汁,由于不需要加載具體的模型類伶椿,所以性能會更高。
例如:
// 使用M方法實例化
//參數(shù):數(shù)據(jù)表名氓侧,不包括數(shù)據(jù)表前綴
$User = M('User');
// 和用法 $User = new \Think\Model('User'); 等效
// 執(zhí)行其他的數(shù)據(jù)操作
$User->select();
M方法也可以支持跨庫操作脊另,例如:
// 使用M方法實例化 操作db_name數(shù)據(jù)庫的ot_user表
$User = M('db_name.User','ot_');
// 執(zhí)行其他的數(shù)據(jù)操作
$User->select();
如果你的模型類有自己的業(yè)務(wù)邏輯,M方法是無法支持的约巷,就算是你已經(jīng)定義了具體的模型類偎痛,M方法實例化的時候是會直接忽略。
D方法
<a>D('[項目://][分組/]模型','模型層名稱')</a>
方法的返回值是實例化的模型對象
<?php
//實例化模型
$User = D('User');
// 相當(dāng)于 $User = new \Home\Model\UserModel();
// 執(zhí)行具體的數(shù)據(jù)操作
$User->select();
//D方法還可以支持跨模塊調(diào)用独郎,需要使用:
//實例化Admin模塊的User模型(admin是默認(rèn)的home目錄等級的)
D('Admin/User');
實例化空模型類
如果你僅僅是使用原生SQL查詢的話踩麦,不需要使用額外的模型類枚赡,實例化一個空模型類即可進(jìn)行操作了,例如:
//實例化空模型谓谦,Model是TP框架提供Model基類
$Model = new Model();
//或者使用M快捷方法是等效的
$Model = M();
//進(jìn)行原生的SQL查詢
$Model->query('SELECT * FROM think_user WHERE status = 1');
實例化空模型類后還可以用table方法切換到具體的數(shù)據(jù)表進(jìn)行操作贫橙,我們在實例化的過程中,經(jīng)常使用D方法和M方法反粥,這兩個方法的區(qū)別在于M方法實例化模型無需用戶為每個數(shù)據(jù)表定義模型類料皇,如果D方法沒有找到定義的模型類,則會自動調(diào)用M方法星压。
數(shù)據(jù)的寫入
向user數(shù)據(jù)表中寫入一條數(shù)據(jù)
$User = M("User"); // 實例化User對象,user是表名
$data['name'] = 'ThinkPHP';
$data['email'] = 'ThinkPHP@gmail.com';
$User->add($data);
數(shù)據(jù)的查詢
(1)讀取數(shù)據(jù)集
讀取數(shù)據(jù)表中的一行數(shù)據(jù)(或者關(guān)聯(lián)數(shù)據(jù)),主要通過find方法完成鬼譬,例如:
$User = M("User"); // 實例化User對象
// 查找status值為1 name值為think的用戶數(shù)據(jù)
//where方法的參數(shù)可以是數(shù)組娜膘、字符串、對象优质,建議用數(shù)組形式
$data = $User->where('status=1 AND name="thinkphp"')->find();
dump($data);
find方法查詢數(shù)據(jù)的時候可以配合相關(guān)的連貫操作方法竣贪,其中最關(guān)鍵的則是where方法。
如果查詢出錯巩螃,find方法返回false演怎,如果查詢結(jié)果為空返回NULL,查詢成功則返回一個關(guān)聯(lián)數(shù)組(鍵值是字段名或者別名)避乏。
<a>即使?jié)M足條件的數(shù)據(jù)不止一個爷耀,find方法也只會返回第一條記錄(可以通過order方法排序后查詢)。</a>
還可以用data方法獲取查詢后的數(shù)據(jù)對象(查詢成功后)
$User = M("User"); // 實例化User對象
// 查找status值為1name值為think的用戶數(shù)據(jù)
$User->where('status=1 AND name="thinkphp"')->find();
dump($User->data());
(2)讀取數(shù)據(jù)集
讀取數(shù)據(jù)集其實就是獲取數(shù)據(jù)表中的多行記錄(以及關(guān)聯(lián)數(shù)據(jù))拍皮,使用select方法歹叮,使用示例:
$User = M("User"); // 實例化User對象
// 查找status值為1的用戶數(shù)據(jù) 以創(chuàng)建時間排序 返回10條數(shù)據(jù)
$list = $User->where('status=1')->order('create_time')->limit(10)->select();
如果查詢出錯,select的返回值是false铆帽,如果查詢結(jié)果為空咆耿,則返回NULL,否則返回二維數(shù)組爹橱。
(3)讀取字段值
讀取字段值其實就是獲取數(shù)據(jù)表中的某個列的多個或者單個數(shù)據(jù)萨螺,最常用的方法是 getField方法。
示例如下:
$User = M("User"); // 實例化User對象
// 獲取ID為3的用戶的昵稱
$nickname = $User->where('id=3')->getField('nickname');
默認(rèn)情況下:當(dāng)只有一個字段的時候愧驱,返回數(shù)據(jù)表中滿足條件的數(shù)據(jù)集的第一行的該字段的值慰技。
如果需要返回整個列的數(shù)據(jù),可以用:
$User->getField('id',true); // 獲取id數(shù)組
//返回數(shù)據(jù)格式如array(1,2,3,4,5)一維數(shù)組冯键,其中value就是id列的每行的值
如果傳入多個字段的話惹盼,默認(rèn)返回一個關(guān)聯(lián)數(shù)組:
$User = M("User"); // 實例化User對象
// 獲取所有用戶的ID和昵稱列表
$list = $User->getField('id,nickname');
//兩個字段的情況下返回的是array(`id`=>`nickname`)的關(guān)聯(lián)數(shù)組,以id的值為key惫确,nickname字段值為value
這樣返回的list是一個數(shù)組手报,鍵名是用戶的id字段的值蚯舱,鍵值是用戶的昵稱nickname。
如果傳入多個字段的名稱掩蛤,例如:
$list = $User->getField('id,nickname,email');
//返回的數(shù)組格式是array(id
=>array(id
=>value,nickname
=>value,email
=>value))是一個二維數(shù)組枉昏,key還是id字段的值,但value是整行的array數(shù)組揍鸟,類似于select()方法的結(jié)果遍歷將id的值設(shè)為數(shù)組key
返回的是一個二維數(shù)組兄裂,類似select方法的返回結(jié)果,區(qū)別的是這個二維數(shù)組的鍵名是用戶的id(準(zhǔn)確的說是getField方法的第一個字段名)阳藻。
如果我們傳入一個字符串分隔符:
$list = $User->getField('id,nickname,email',':');
那么返回的結(jié)果就是一個數(shù)組晰奖,鍵名是用戶id,鍵值是 nickname:email的輸出字符串腥泥。
getField方法還可以支持限制數(shù)量匾南,例如:
$this->getField('id,name',5); // 限制返回5條記錄
$this->getField('id',3); // 獲取id數(shù)組 限制3條記錄
可以配合使用order方法使用。
數(shù)據(jù)的更新
更新一條或多條記錄用save
更新數(shù)據(jù)使用save方法蛔外,例如:
$User = M("User"); // 實例化User對象
// 要修改的數(shù)據(jù)對象屬性賦值
$data['name'] = 'ThinkPHP';
$data['email'] = 'ThinkPHP@gmail.com';
$User->where('id=5')->save($data); // 根據(jù)條件更新記錄
也可以改成對象方式來操作:
$User = M("User"); // 實例化User對象
// 要修改的數(shù)據(jù)對象屬性賦值
$User->name = 'ThinkPHP';
$User->email = 'ThinkPHP@gmail.com';
$User->where('id=5')->save(); // 根據(jù)條件更新記錄
數(shù)據(jù)對象賦值的方式蛆楞,save方法無需傳入數(shù)據(jù),會自動識別夹厌。
注意:save方法的返回值是影響的記錄數(shù)豹爹,如果返回false則表示更新出錯,因此一定要用恒等來判斷是否更新失敗矛纹。
注意:為了保證數(shù)據(jù)庫的安全臂聋,避免出錯更新整個數(shù)據(jù)表,如果沒有任何更新條件或者數(shù)據(jù)對象本身也不包含主鍵字段的話崖技,save方法不會更新任何數(shù)據(jù)庫的記錄逻住。
因此下面的代碼不會更改數(shù)據(jù)庫的任何記錄
$User->save($data);
<a>要修改的數(shù)據(jù)必須要有條件或者主鍵</a>
除非使用下面的方式(假如id字段是主鍵):
$User = M("User"); // 實例化User對象
// 要修改的數(shù)據(jù)對象屬性賦值
$data['id'] = 5; //要修改的數(shù)據(jù)必須要有條件或者主鍵
$data['name'] = 'ThinkPHP';
$data['email'] = 'ThinkPHP@gmail.com';
$User->save($data); // 根據(jù)條件保存修改的數(shù)據(jù)
字段和數(shù)據(jù)過濾
和add方法一樣,save方法支持使用field方法過濾字段和filter方法過濾數(shù)據(jù)迎献,例如:
$User = M("User"); // 實例化User對象
// 要修改的數(shù)據(jù)對象屬性賦值
$data['name'] = 'test';
$data['email'] = '<b>test@gmail.com</b>';
//field方法用于指定要修改的的字段
//strip_tags:過濾HTML標(biāo)簽
$User->where('id=5')->field('email')->filter('strip_tags')->save($data); // 根據(jù)條件保存修改的數(shù)據(jù)
當(dāng)使用field('email')的時候瞎访,只允許更新email字段的值(采用strip_tags方法過濾),name字段的值將不會被修改吁恍。
還有一種方法是通過create或者data方法創(chuàng)建要更新的數(shù)據(jù)對象扒秸,然后進(jìn)行保存操作,這樣save方法的參數(shù)可以不需要傳入冀瓦。
$User = M("User"); // 實例化User對象
// 要修改的數(shù)據(jù)對象屬性賦值
$data['name'] = 'ThinkPHP';
$data['email'] = 'ThinkPHP@gmail.com';
$User->where('id=5')->data($data)->save(); // 根據(jù)條件保存修改的數(shù)據(jù)
使用create方法的例子:
$User = M("User"); // 實例化User對象
// 根據(jù)表單提交的POST數(shù)據(jù)創(chuàng)建數(shù)據(jù)對象
$User->create();
$User->save(); // 根據(jù)條件保存修改的數(shù)據(jù)
更新字段
如果只是更新個別字段的值伴奥,可以使用setField方法。
使用示例:
$User = M("User"); // 實例化User對象
// 更改用戶的name值
$User-> where('id=5')->setField('name','ThinkPHP');
setField方法支持同時更新多個字段翼闽,只需要傳入數(shù)組即可拾徙,例如:
$User = M("User"); // 實例化User對象
// 更改用戶的name和email的值
$data = array('name'=>'ThinkPHP','email'=>'ThinkPHP@gmail.com');
$User-> where('id=5')->setField($data);
而對于統(tǒng)計字段(通常指的是數(shù)字類型)的更新,系統(tǒng)還提供了setInc和setDec方法感局。
$User = M("User"); // 實例化User對象
$User->where('id=5')->setInc('score',3); // 用戶的積分加3
$User->where('id=5')->setInc('score'); // 用戶的積分加1
$User->where('id=5')->setDec('score',5); // 用戶的積分減5
$User->where('id=5')->setDec('score'); // 用戶的積分減1
3.2.3版本開始尼啡,setInc和setDec方法支持延遲更新暂衡,用法如下:
$Article = M("Article"); // 實例化Article對象
$Article->where('id=5')->setInc('view',1); // 文章閱讀數(shù)加1
$Article->where('id=5')->setInc('view',1,60); // 文章閱讀數(shù)加1,并且延遲60秒更新(寫入)
數(shù)據(jù)的刪除
ThinkPHP刪除數(shù)據(jù)使用delete方法崖瞭,例如:
$Form = M('Form');
$Form->delete(5);
表示刪除主鍵為5的數(shù)據(jù)狂巢,delete方法可以刪除單個數(shù)據(jù),也可以刪除多個數(shù)據(jù)书聚,這取決于刪除條件唧领,例如:
$User = M("User"); // 實例化User對象
$User->where('id=5')->delete(); // 刪除id為5的用戶數(shù)據(jù)
$User->delete('1,2,5'); // 刪除主鍵為1,2和5的用戶數(shù)據(jù)
$User->where('status=0')->delete(); // 刪除所有狀態(tài)為0的用戶數(shù)據(jù)
delete方法的返回值是刪除的記錄數(shù),如果返回值是false則表示SQL出錯雌续,返回值如果為0表示沒有刪除任何數(shù)據(jù)斩个。
也可以用order和limit方法來限制要刪除的個數(shù),例如:
// 刪除所有狀態(tài)為0的5 個用戶數(shù)據(jù) 按照創(chuàng)建時間排序
$User->where('status=0')->order('create_time')->limit('5')->delete();
為了避免錯刪數(shù)據(jù)驯杜,如果沒有傳入任何條件進(jìn)行刪除操作的話萨驶,不會執(zhí)行刪除操作,例如:
$User = M("User"); // 實例化User對象
$User->delete();
不會刪除任何數(shù)據(jù)艇肴,如果你確實要刪除所有的記錄,除非使用下面的方式:
$User = M("User"); // 實例化User對象
$User->where('1')->delete();
附錄:
1叁温、常用API詳解文檔