Yii2框架中一些折磨人的坑(2)
问题总结
这段代码的问题在于:
- 大家知道$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,世界就清净了。所以,如果你遇到这种问题,感激我吧。
内存泄露
代码现场
public static function actionTest() { $total = 10; var_dump('开始内存'.memory_get_usage()); while($total){ $ret=User::findOne(['id'=>910002]); var_dump('end内存'.memory_get_usage()); unset($ret); $total--; } }
上面代码的内存一直在增长, 按照原本想法来看, 变量被释放了,内存就算增长也不会一直增长。因为每循环一次内存都会被释放。
分析问题 上面这段代码涉及到了数据库的操作,而我们知道,数据库的很多地方都能引起内存泄漏。 所以先屏蔽数据库相关操作, 我手写了一个原生的数据库查询操作, 发现内存正常,没有问题。
$dsn = "mysql:dbname=test;host=localhost"; $db_user = 'root'; $db_pass = 'admin'; //查询 $sql = "select * from buyer"; $res = $pdo->query($sql); foreach($res as $row) { echo $row['username'].'<br/>'; }
这时候答案呼之欲出--- 是yii2框架搞了鬼
定位问题 既然知道了是yii2 框架的问题那就可以进一步缩小问题。
public static function actionTest() { $total = 10; var_dump('开始内存'.memory_get_usage()); while($total){ $ret= new User(); var_dump('end内存'.memory_get_usage()); unset($ret); $total--; } }
内存还是一直增长。 这时候我测试了一个其他的yii2类 发觉内存不增长了。 这就可以联想到是在new 对象的时候yii2内部自己执行了什么操作,然后导致内存泄漏。 什么方法是new 的时候就执行的呢。。。 对的 构造方法 __construct 。 然后 我一步一步的从model 查到object 发觉都没有能引起泄漏的地方。