thinkPHP學(xué)習(xí)筆記之?dāng)?shù)據(jù)庫操作(二)

上一節(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)還提供了setIncsetDec方法感局。

$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詳解文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末再悼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子膝但,更是在濱河造成了極大的恐慌冲九,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件跟束,死亡現(xiàn)場離奇詭異莺奸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冀宴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門灭贷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人略贮,你說我怎么就攤上這事甚疟。” “怎么了逃延?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵览妖,是天一觀的道長。 經(jīng)常有香客問我揽祥,道長讽膏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任拄丰,我火速辦了婚禮府树,結(jié)果婚禮上俐末,老公的妹妹穿的比我還像新娘。我一直安慰自己挺尾,他們只是感情好圾旨,可當(dāng)我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布效床。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪珊拼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天链患,我揣著相機(jī)與錄音慧邮,去河邊找鬼。 笑死涂召,一個胖子當(dāng)著我的面吹牛坠非,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播果正,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炎码,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秋泳?” 一聲冷哼從身側(cè)響起潦闲,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎迫皱,沒想到半個月后歉闰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡卓起,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年和敬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片戏阅。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡昼弟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奕筐,到底是詐尸還是另有隱情私杜,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布救欧,位于F島的核電站衰粹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏笆怠。R本人自食惡果不足惜铝耻,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瓢捉,春花似錦频丘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至某弦,卻和暖如春桐汤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背靶壮。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工怔毛, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腾降。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓拣度,卻偏偏與公主長得像,于是被迫代替她去往敵國和親螃壤。 傳聞我的和親對象是個殘疾皇子抗果,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容