您的位置:首页 > 编程语言 > PHP开发

Yii2框架的几个隐蔽的坑

2016-06-24 11:12 477 查看

Yii2框架的几个隐蔽的坑

摘要:Yii2是一款优秀的通用Web后端框架,结构简单优雅、实用功能丰富、扩展性强、性能搞是他最突出的优点。它优秀的地方你在使用过程中总能轻易的发现,无须赘述。而这些隐蔽的小瑕疵,显得更有必要告诉大家。

博客: http://www.cnblogs.com/jhzhu

邮箱: jhzhuustc@gmail.com

作者: 知明所以

时间: 2015-08-17

目录

Yii2框架的几个隐蔽的坑

目录

说点闲话

ActiveRecord被莫名写入?

准备知识

代码现场

总结问题

解决方法

你的Transaction生效了吗?

代码现场

问题总结

解决方法

'Y-m-d'不被识别?

代码现场

问题总结

说点闲话

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

值得庆祝的一件事:最近开始,每天早上8:30起来健身了。有两个视频很好用,只需8分钟,照着做一遍保证你(生)爽(不)到(如)爆(死)。(8分钟腹肌锻炼第2级-下载8分钟胸肌锻炼第2级-下载

值得反思的一件事:最近看了《叔本华美学随笔》,改变了我一直以来对阅读的看法。我曾经以为阅读是进步的源动力,却被这本书深深的打脸了。来,先给大家分享一段:

我 们只管所见的外在环境并不像阅读物那样,把某已确定的见解强加给我们的头脑,而只是为我们提供了素材和机会。去思考与我们的头脑能力相称、与当下的情绪相 符的事情。所以,太多的阅读会是我们的精神失去弹性,就像把一重物持续压在一条弹簧上面就会是弹簧失去弹性一样;而让自己没有自己思想的最稳妥的办法就是 在空闲的每一分钟马上随手拿起一本书。

思考才是进步的源动力

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

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(); //保存,会发现此行的其它字段都被写成默认值了。

总结问题

这个例子的问题在于:

我从数据库中取出了一行,也就是代码中的$room,但是只取出了id字段,而其他字段自然就是默认值。

当我$room->save()的时候,那些是默认值的字段也被保存到数据库里去了。what!?

也就是说,当你想节约资源,不取出所有字段的时候,一定要注意不能保存,否则,很多数据会被莫名修改为默认值。

解决方法

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

自己时刻注意,避免未完全取出的ActiveRecord的保存。

修改或继承ActiveRecord, 使得,当此对象由find()新建,且字段没有完全取出,调用save()方法,抛出异常。

修改或继承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();

}

问题总结

这段代码的问题在于:

大家知道$transaction的存在意义是保证整段数据库存储代码要么全成功,要么全失败。

显然,在这个例子中,transaction并没有达到我们想要的效果:$a因为validate()都没过,所以$transation->commit()的时候并不会报错。

解决方法

在$transation块内,所有的save()都要判断下返回值,如果为false,则直接抛出异常。

'Y-m-d'不被识别?

代码现场

OcRenterBill extends ActiveRecord

{

public function rules()

{

return [

['start_time','date','format'=>'Y-m-d'],

];

}

}

$a = new OcRenterBill();

$a = '2015-09-12';

$a->save(); //会报错,说格式不对。

问题总结

如果一开始,Yii框架就报错,这个还不算坑。坑的是我在Mac上开发时,这个可以完全正常的工作,而发布到线上环境(Ubuntu)后,就弹出“属性start_time格式无效”的错误。而参考官方文档,发现这种格式是允许的官方文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: