上一期 如何寫(xiě)一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(6) - 查詢(xún) - WHERE篇
下一期 如何寫(xiě)一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(8) - CREATE篇
基本思路
在開(kāi)始代碼之前, 我們需要回想一些日常面對(duì)的難題, 或則說(shuō)不良體驗(yàn)
在實(shí)現(xiàn)業(yè)務(wù)邏輯時(shí), 我們往往都會(huì)遇到以下類(lèi)似場(chǎng)景
確認(rèn)A先生(id=233)是否會(huì)員, 如果是, 修改字段'status'為'active', 否則刪除它
在沒(méi)有框架的時(shí)候一般都會(huì)這么寫(xiě)的(以下代碼略過(guò)所有pdo邏輯)
// 首先查詢(xún)A先生的數(shù)據(jù), 獲取他的身份
$a = 'select * from users where id = 233';
// 判定是否為會(huì)員
if($a->member === true)
// 是就修改字段
$b = 'update users set status = 'active' where id = 233';
else
// 否就刪除數(shù)據(jù)
$b= 'delete from users where id = 233';
注意, 這是因?yàn)槲覀兒?jiǎn)略了pdo的所有步驟, 試想想更復(fù)雜的業(yè)務(wù)邏輯, 曾經(jīng)見(jiàn)過(guò)滿滿上千行都是SQL語(yǔ)句的, 代碼可讀性等于0, 重構(gòu)無(wú)能
所以,憑什么我們需要寫(xiě)的這么多呢, 可以簡(jiǎn)化啊!
可再操作的數(shù)據(jù)
當(dāng)數(shù)據(jù)返回后,將其轉(zhuǎn)化為實(shí)例, 該實(shí)例附帶函數(shù), 可以進(jìn)行某些操作
這就是查詢(xún) - 入門(mén)篇中為什么數(shù)據(jù)返回后會(huì)被放入函數(shù)cast()當(dāng)中進(jìn)行轉(zhuǎn)化的原因
使用封裝后可以這么做
// 首先查詢(xún)A先生的數(shù)據(jù), 獲取他的身份
$a = User::find(233);
// 判定是否存在該id和該id是否為會(huì)員
if($a & $a->member)
// 是就修改字段
$b = $a->update(['status'=>'active']);
else
// 否就刪除數(shù)據(jù)
$b= $a->delete();
接下來(lái)我們需要思考
如何對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)進(jìn)行修改?
這是我自己的膚淺答案
常見(jiàn)的情況我們需要用到條件語(yǔ)法, 對(duì)需要修改的數(shù)據(jù)指定范圍, 過(guò)濾無(wú)需改寫(xiě)的數(shù)據(jù)
根據(jù)以上的說(shuō)明, 有三種例子
1.完全不指定范圍, 修改表內(nèi)所有數(shù)據(jù)
update Actor set first_name = 'new data'
2.指定范圍, 修改匹配條件的多條數(shù)據(jù)
update Actor set first_name = 'new data' where first_name like '%L%'
3.指定范圍, 依據(jù)表的 identity key 或 unique key 修改指定單條數(shù)據(jù)
update Actor set first_name = 'new data' where actor_id = 10
根據(jù)以上的三種類(lèi)型, 我們可以開(kāi)始開(kāi)發(fā)update函數(shù)了,
PS:過(guò)于高級(jí)的update語(yǔ)句我因?yàn)榻?jīng)驗(yàn)尚淺無(wú)法理解/不曾使用, 歡迎留言
Builder.php
在最后一行添加update函數(shù)
// 改寫(xiě)數(shù)據(jù)庫(kù)數(shù)據(jù)
public function update(array $values) {
// 如果寫(xiě)保護(hù)已經(jīng)開(kāi)啟,跳出錯(cuò)誤
if($this->writeLock) throw new Exception("data is not allow to update");
// 編譯update語(yǔ)句
$sql = $this->grammar->compileUpdate($this, $values);
// 將所有變量的值合成一個(gè)數(shù)組, 其中包括條件語(yǔ)句部分
$bindings = array_values(array_merge($values, $this->getBindings()));
// 返回改寫(xiě)結(jié)果调塌,成功true失敗false
return $this->connector->update($sql, $bindings);
}
Grammar.php
在最后一行添加compileUpdate函數(shù)
public function compileUpdate(Builder $query, $values) {
// 循環(huán)$values, 記得引用
foreach ($values as $key => &$value)
// 將所有$value改成對(duì)應(yīng)的$key=?
$value = $key.' = ?';
// 將$values中的之全部掏出在連接起來(lái)
$columns = implode(', ', array_values($values));
// 附上where語(yǔ)句如果有
// 由于更復(fù)雜的sql update語(yǔ)句我還沒(méi)試過(guò), 為了不坑人, 所以限制只有where語(yǔ)法有效
// 歡迎提供更復(fù)雜的where語(yǔ)句
$where = is_null($query->wheres) ? '' : $this->compileWheres($query);
// 返回update語(yǔ)句
return trim("update $query->from set $columns $where");
}
Model.php
添加函數(shù) save, 用法見(jiàn)下面例子
// 一種更快捷的update方式
public function save() {
return $this->update((array)$this->data);
}
例子
- 修改指定數(shù)據(jù)
$a = Actor::where('first_name', 'ANGELINA')
->update(['last_name'=>'changed']);
dd($a);
- 再操作數(shù)據(jù)實(shí)例
$a = Actor::where('first_name', 'ANGELINA')
->first();
dd($a->update(['last_name'=>'again']));
- 再操作數(shù)據(jù)實(shí)例, 另一種用法
$a = Actor::where('first_name', 'ANGELINA')
->first();
$a->last_name = 'save';
dd($a->save());
返回結(jié)果
boolean true
// 失敗返回 false
完整代碼
源代碼放在coding.net里, 自己領(lǐng)
上一期 如何寫(xiě)一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(6) - 查詢(xún) - WHERE篇
下一期 如何寫(xiě)一個(gè)屬于自己的數(shù)據(jù)庫(kù)封裝(8) - CREATE篇