例如:我們有測試表,它有3列:id,watchers,title。 我們有一個代碼:如何在Yii中保存數據並確保正確保存?
$test = Test::model()->findByPk(1);
echo $test->watchers; // 0
$test->title = 'another';
$test->save();
當我們調用save()IR產生像"UPDATE test SET title='another', watchers='0' WHERE id='1'"
SQL查詢。所以,一切接縫都可以。但問題是,如果另一個進程在findByPk和保存在當前腳本之間的時間內更新watchers變量,代碼將生成錯誤的值。所以:
$test = Test::model()->findByPk(1);
echo $test->watchers; // 0
$test->title = 'another';
//HERE WE HAVE A CODE WHICH PERFORMS FOR 1 SECOND. MEANWHILE ANOTHER PROCESS
// UPDATES TABLE WITH WATCHERS = 1
$test->save();
所以,這段代碼會將記錄的觀察者字段保存回0.如何克服這個問題?爲什麼Yii ORM不保存只有更改了值?爲什麼它試圖保存所有值?謝謝。
我建議@Criesto的答案,你也可以使用TRANSACTIN(如果數據庫引擎是InnoDB):http://www.yiiframework.com/doc/api/1.1/CDbTransaction它阻塞表,所以另一個查詢必須「等待」事務提交或回滾之前。 –
@ Criesto的回答不好,因爲我不想在存儲數據的地方重寫每一段代碼。這個問題是項目範圍內的,我必須重寫所有代碼,而不僅僅是關鍵。關於交易 - 您確定將交易添加到每一次更新是一個好主意嗎?在任何情況下,事務都不能解決問題,因爲問題在於由Yii生成的錯誤代碼,而不是MySQL的一致性。需要修補Yii。事實上,save()方法在Yii2中的工作方式完全相同,這證明了我的建議。 – Volodymyr
您可以從CActiveRecord(f.e. ActiveRecord)擴展的類來擴展所有的模型。所以你只需要將模型的父類改爲ActiveRecord並在ActiveRecord中重寫save()方法。您也可以根據需要覆蓋其他使用數據庫的方法,並且無需在使用CRUD方法的情況下更改整個代碼。 –