简体   繁体   English

如何在Yii中保存数据并确保正确保存?

[英]how to save data in Yii and be sure on correct saving?

Example: we have test table, which has 3 columns: id, watchers, title. 示例:我们有一个测试表,该表有3列:id,观察者,标题。 We have a code: 我们有一个代码:

$test = Test::model()->findByPk(1);
echo $test->watchers; // 0
$test->title = 'another';
$test->save();

When we call save() ir generates sql query like "UPDATE test SET title='another', watchers='0' WHERE id='1'" . 当我们调用save()时,ir会生成sql查询,例如"UPDATE test SET title='another', watchers='0' WHERE id='1'" SO, seams like everything is okay. 所以,接缝就像一切都很好。 But the problem is that if some another process will update watchers variable in the time between findByPk and save in current script, the code will generate wrong value. 但是问题在于,如果某个其他进程将在findByPk与保存在当前脚本之间的时间内更新watchers变量,则代码将生成错误的值。 So: 所以:

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

So, this code will save record's watchers field back to 0. How to overcome this? 因此,此代码会将记录的watchers字段保存回0。如何克服这个问题? Why Yii ORM doesn't save only changed values? 为什么Yii的ORM不救不仅改变值? Why it tries to save all values? 为什么要尝试保存所有值? Thank you. 谢谢。

Since you get each value in $test , so when you do $test->save(); 因为您在$test获得了每个值,所以当您执行$test->save(); every attribute gets saved with new record or the previous value it contained. 每个属性都保存有新记录或其包含的先前值。

When you query $test = Test::model()->findByPk(1); 当您查询$test = Test::model()->findByPk(1); then $test->watchers; 然后$test->watchers; will be the same value which was there when you executed the query, this value will only change (if the value of watchers was changed by another update query) when you do another select query. 将与执行查询时的值相同,仅当您执行另一个select查询时,此值才会更改(如果观察者的值已由另一个update查询更改)。 Hope that makes sense :P 希望有意义:P

You can try the following update method : 您可以尝试以下更新方法:

Test::model()->updateByPk(1, array(
                'title' => 'another'
            ));

Which will execute the following query: 它将执行以下查询:

UPDATE `test` SET `title`=:yp0 WHERE `test`.`id`=1.
Bound with :yp0='another'

I would tackle the issue as such: 我将这样解决这个问题:

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

{or} {要么}

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

As for me, the best solution is to inherit and rewrite the save() method and do it's behaviour the same as it is in Yii2 (getDirtyAttributes() method). 对我而言,最好的解决方案是继承并重写save()方法,并使其行为与Yii2(getDirtyAttributes()方法)相同。 W must compar eattributes to fetched from the db attributes and save only those ones, which were modified. W必须比较从db属性获取的属性,并仅保存已修改的属性。 I've successfully implemented this and can cinfirm it works. 我已经成功实现了这一点,并且可以肯定它的有效性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM