示例:我们有测试表,它有3列:id,watchers,title。 我们有一个代码:
$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之间的时间内更新观察者变量并保存在当前脚本中,则代码将生成错误的值。所以:
$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不保存仅更改的值?为什么它试图保存所有值?谢谢。
答案 0 :(得分:2)
由于您获得$test
中的每个值,因此当您执行$test->save();
时,每个属性都会使用新记录或其包含的先前值保存。
当您查询$test = Test::model()->findByPk(1);
时,$test->watchers;
将与您执行查询时的值相同,此值只会更改(如果观察者的值已被另一个{{1}更改} query,当你做另一个update
查询时。希望有道理:P
您可以尝试以下更新方法:
select
将执行以下查询:
Test::model()->updateByPk(1, array(
'title' => 'another'
));
答案 1 :(得分:1)
我会解决这个问题:
$test = Test::model()->findByPk(1);
$test->title = 'another';
/*according to the api the second parameter only saves the columns
that are mentioned in the array. In this case it will save just the
title
*/
$test->save(true,array('title'));
<强> {或} 强>
$test = Test::model()->findByPk(1);
$test->title = 'another';
/*according to the api the parameter only saves the columns
that are mentioned in the array. In this case it will save just the
title
*/
$test->saveAttributes(array('title'));
答案 2 :(得分:0)
对我来说,最好的解决方案是继承和重写save()方法,并将其行为与Yii2(getDirtyAttributes()方法)中的行为相同。 W必须比较从db属性获取的属性并仅保存那些已修改的属性。我已成功实施此功能,并可确认其有效。