Yii2框架的几个隐蔽的坑
摘要:Yii2是一款优秀的通用Web后端框架,结构简单优雅、实用功能丰富、扩展性强、性能搞是他最突出的优势。它优秀的地方你在使用过程当中总能轻易的发现,无须赘述。而这些隐蔽的小瑕疵,显得更有必要告诉你们。php
- 博客: http://www.cnblogs.com/jhzhu
- 邮箱: jhzhuustc@gmail.com
- 做者: 知明因此
- 时间: 2015-08-17
目录
说点闲话
距离上次写博客,已经有三个月了。在动手写以前,老是带着深深的罪恶感。被它折磨许久,终于,仍是,动手了。css
值得庆祝的一件事:最近开始,天天早上8:30起来健身了。有两个视频很好用,只需8分钟,照着作一遍保证你(生)爽(不)到(如)爆(死)。(8分钟腹肌锻炼第2级-下载,8分钟胸肌锻炼第2级-下载)html
值得反思的一件事:最近看了《叔本华美学随笔》,改变了我一直以来对阅读的见解。我曾经觉得阅读是进步的源动力,却被这本书深深的打脸了。来,先给你们分享一段:git
咱们只管所见的外在环境并不像阅读物那样,把某已肯定的看法强加给咱们的头脑,而只是为咱们提供了素材和机会。去思考与咱们的头脑能力相称、与当下的情绪相符的事情。因此,太多的阅读会是咱们的精神失去弹性,就像把一重物持续压在一条弹簧上面就会是弹簧失去弹性同样;而让本身没有本身思想的最稳妥的办法就是在空闲的每一分钟立刻随手拿起一本书。github
思考才是进步的源动力!web
好了,扯淡完毕,步入正题。数据库
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(); //保存,会发现此行的其它字段都被写成默认值了。
总结问题
这个例子的问题在于:canvas
- 我从数据库中取出了一行,也就是代码中的
$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(); }
问题总结
这段代码的问题在于:yii2
- 你们知道
$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格式无效”的错误。而参考官方文档,发现这种格式是容许的官方文档。
啊啊啊。各类试错,最后发现若是改为php:Y-m-d
,世界就清净了。因此,若是你遇到这种问题,感激我吧。