Phalcon入門教程之模型CURD(2)
原文發表於:Phalcon入門教程之模型CURD(2)
上一篇 Phalcon入門教程之模型CURD(1) 中介紹了 Phalcon
模型的 insert
和 select
操作,本篇將介紹 update
和 delete
的用法。文中所用的示例代碼皆沿用上一篇的數據表,這裏不在贅述。
更新記錄
Phalcon
模型更新記錄的示例代碼如下:
$articleModel = new ArticlesModel();
//先調用 findFirst() 獲取一條記錄,返回值是當前模型對象
$article = $articleModel->findFirst([
'conditions' => 'aid = :aid:',
'bind' => [
'aid' => 3
],
]);
if($article) {
//使用返回的模型對象調用 update() 函數執行更新操作
$result = $article->update([
'title' => 'Phalcon更新測試1',
]);
//update() 函數返回值為boolean
var_dump($result);
}
監聽到的SQL語句如下:
SELECT * FROM `test_articles` WHERE `test_articles`.`aid` = :aid LIMIT :APL0
UPDATE `test_articles` SET `title` = ?, `introduce` = ?, `status` = ?, `view_number` = ?, `is_recommend` = ?, `is_top` = ?, `create_by` = ?, `create_time` = ?, `modify_by` = ?, `modify_time` = ? WHERE `aid` = ?
通過代碼和SQL語句,可以看出在調用 update()
函數之前,必須要先調用 findFirst()
函數獲取一條記錄。這是因為 update()
函數內部是默認使用主鍵作為更新條件的,所以 update()
函數沒有**更新條件**這個參數,隻能通過主鍵來更新。但是每次執行更新操作的時候,都要執行兩條SQL語句(先 select
後 update
),在性能上會有所損耗。下麵跟大家分享隻執行一條 update
SQL語句的辦法( 前提是已經知道主鍵值):
$articleModel = new ArticlesModel();
$articleModel->aid = 3; //為主鍵成員屬性賦值
$result = $articleModel->update([
'title' => 'Phalcon更新測試',
]);
上述代碼運行之後,拋出一個異常:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'introduce' cannot be null
意思是 introduce
字段值不能為空。我們回頭再看前麵監聽到的 update
SQL語句,執行 update()
函數的時候,把 test_articles
表中的所有字段都更新了。也就是說,**調用 update()
函數的時候,需要更新表中的所有字段,而不能隻更新某個字段或者一部分字段**,所以此處,需要傳入全部字段做為參數:
$articleModel = new ArticlesModel();
$articleModel->aid = 3;
$result = $articleModel->update([
'title' => 'Phalcon更新測試',
'introduce' => "Phalcon入門教程2",
'status' => 2,
'view_number' => 2,
'is_recommend' => 1,
'is_top' => 1,
'create_by' => 1,
'create_time' => date('Y-m-d H:i:s'),
'modify_by' => 1,
'modify_time' => date('Y-m-d H:i:s')
]);
if(!$result){
throw new \Exception('數據更新失敗');
}
//獲取影響行數(假設DI中注冊的數據庫服務名稱為“db”)
$affectedRows = $this->getDI()->get('db')->affectedRows();
每次更新數據的時候,都需要將所有字段全部更新,顯然不符合咱天朝廣大開發者的習慣,那有沒有辦法實現隻更新部分字段呢?
更新部分字段
除了寫原生SQL,或者通過PHQL的方式可以實現更新部分字段之外,Phalcon
中並沒有提供可以直接使用的函數。不過,我們可以通過其他方法來曲線救國一下,下麵是我封裝的函數:
//文件路徑:marser/app/frontend/models/ArticlesModel.php
/**
* 封裝phalcon model的update函數,實現僅更新數據變更字段,而非所有字段更新
* @param array|null $data
* @param null $whiteList
* @return bool
*/
public function iupdate(array $data = null, $whiteList = null)
{
if (count($data) > 0) {
//獲取當前模型驛應的數據表所有字段
$attributes = $this->getModelsMetaData()->getAttributes($this);
//取所有字段和需要更新的數據字段的差集,並過濾
$this->skipAttributesOnUpdate(array_diff($attributes, array_keys($data)));
}
return parent::update($data, $whiteList);
}
函數很簡單,先獲取當前模型對應數據表的所有字段,並和需要更新的數據字段之間取差集,然後調用 skipAttributesOnUpdate
函數進行過濾。上述更新部分字段的示例代碼就可以修改成:
$articleModel = new ArticlesModel();
$articleModel->aid = 3;
//注意這裏的函數名
$result = $articleModel->iupdate([
'title' => 'Phalcon更新測試',
]);
if(!$result){
throw new \Exception('數據更新失敗');
}
$affectedRows = $this->getDI()->get('db')->affectedRows();
至此就能更新成功,並能獲取影響行數。
這裏提一下,Phalcon
模型的 update()
函數有一個注意點。當更新的數據和表中的數據相同時,update()
函數會返回 true
值,但是影響行數卻是0。
save()
Phalcon
模型的 save()
函數會判斷當前模型對象中主鍵成員屬性是否有值,若有值,就內部調用 update()
函數執行更新操作;若沒值,就內部調用 create()
函數執行插入操作。
刪除記錄
刪除記錄和更新記錄類似,要先調用 findFirst()
之後,再調用 delete()
函數刪除一條數據。我們在知道主鍵的情況,也可以直接給主鍵成員屬性賦值:
$articleModel = new ArticlesModel();
$articleModel->aid = 4;
$result = $articleModel->delete();
$affectedRows = $this->getDI()->get('db')->affectedRows();
值得注意的是,不論主鍵ID是否存在,delete()
都會返回 true
值,而影響行數會正常返回。所以建議根據影響行數來判斷是否執行成功。
如果需要批量刪除,或者使用非主鍵作為刪除條件,那麼隻能寫原生SQL或者PHQL去刪除數據,當然也可以自己封裝一個函數。
以上代碼已托管在github:https://github.com/KevinJay/marser-phalcon-demo
最後,歡迎大家加入QQ群交流討論:
- 廣州PHP高端交流群:158587573
- Phalcon玩家群:150237524
最後更新:2017-07-20 17:02:54