Phalcon入門教程之模型CURD(2)

原文發表於:Phalcon入門教程之模型CURD(2)php

上一篇 Phalcon入門教程之模型CURD(1) 中介紹了 Phalcon 模型的 insertselect 操做,本篇將介紹 updatedelete 的用法。文中所用的示例代碼皆沿用上一篇的數據表,這裏不在贅述。html

更新記錄

Phalcon 模型更新記錄的示例代碼以下:git

$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語句以下:github

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語句(先 selectupdate ),在性能上會有所損耗。下面跟你們分享只執行一條 update SQL語句的辦法( 前提是已經知道主鍵值):shell

$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() 函數的時候,須要更新表中的全部字段,而不能只更新某個字段或者一部分字段,因此此處,須要傳入所有字段作爲參數:app

$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();

每次更新數據的時候,都須要將全部字段所有更新,顯然不符合咱天朝廣大開發者的習慣,那有沒有辦法實現只更新部分字段呢?frontend

更新部分字段

除了寫原生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/m...

最後,歡迎你們加入QQ羣交流討論:

  • 廣州PHP高端交流羣:158587573
  • Phalcon玩家羣:150237524
相關文章
相關標籤/搜索