Yii2框架中一些折磨人的坑

说点闲话

距离上次写博客,已经有一年了。在动手写之前,总是带着深深的罪恶感。被它折磨许久,终于,还是,动手了。

值得庆祝的一件事:最近开始健身了。每天动感单车45分钟,游泳45分钟,真的是(生)爽(不)到(如)爆(死)。

好了,扯淡完毕,步入正题。

ActiveRecord被莫名写入?

准备知识

ActiveRecord的基本用法。如果不理解,可参考这里。

代码现场

/**
 * @property integer $id
 * @property string $name
 * @property string $detail
 * @property double $price
 * @property integer $area
 **/
class OcRoom extends ActivieRecord
{
 ...
}

$room = OcRoom::find()  //先取出一个对象。
 ->select(['id'])  //只取出'id'列
 ->where(['id'=>20])
 ->one();
$room->save();    //保存,会发现此行的其它字段都被写成默认值了。

总结问题

这个例子的问题在于:

  1. 我从数据库中取出了一行,也就是代码中的$room,但是只取出了id字段,而其他字段自然就是默认值。
  2. 当我$room->save()的时候,那些是默认值的字段也被保存到数据库里去了。what!?
  3. 也就是说,当你想节约资源,不取出所有字段的时候,一定要注意不能保存,否则,很多数据会被莫名修改为默认值。

解决方法

然而,我们有什么解决办法呢?提供几种思路:

  1. 自己时刻注意,避免未完全取出的ActiveRecord的保存。
  2. 修改或继承ActiveRecord, 使得,当此对象由find()新建,且字段没有完全取出,调用save()方法,抛出异常。
  3. 修改或继承ActiveRecord,使得,当此对象由find()新建,且字段没有完全取出,调用save()方法时,只保存取出过的字段,其他字段被忽略。

你的Transaction生效了吗?

代码现场

/**
 * @property integer $id
 * @property string $name
 **/
class OcRoom extends ActiveRecord
{
 public function rules()
 {
  return [['name','string','min'=>2,'max'=>10]];
 }
 ...
}
class OcHouse extends ActiveRecord
{
 public function rules()
 {
  return [['name','string','max'=>10]];
 }
 ...
}

$a = new OcRoom();
$a->name = '';    //name为空字符串,不满足rules()条件。

$b = new OcHouse();
$b->name = '我的房间';   //name合法,可以保存。

$transaction = Yii::$app->db->beginTransaction();
try{
 $a->save();    //name字段不合法,无法验证通过,在validate()阶段已经返回false,不会进行数据库存储的步骤,所以也不会抛出异常。
 $b->save();    //name字段合法,可以正常保存。

 $transaction->commit(); //提交后,发现$a保存失败,而$b保存成功。
}
catch (Exception $e) 
{
 Yii::error($e->getTraceAsString(),__METHOD__);
 $transaction->rollBack();
}
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/1771.html