閱讀206 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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

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

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

更新記錄

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語句(先 selectupdate ),在性能上會有所損耗。下麵跟大家分享隻執行一條 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

  上一篇:go  二甲基二乙烯基矽烷 IOTA 501
  下一篇:go  Phalcon入門教程之模型CURD(1)