albin
- albin 评论了教程 (深入研究)记一个yii2下面的内存泄漏问题
每一次循环之后,执行:
gc_collect_cycles();
php7下测试有效,可以释放内存,很好用。
内存释放之后,不仅不会内存溢出了,脚本执行速度也快了很多 我也遇到了这个问题,研究了很长时间,后来决定看源代码。
打开 vendor/yiisoft/yii2/base/Model.phpload()方法调用了setAttributes($values, $safeOnly = true)。
$values就是我们post过来的数据,$safeOnly没有理解,默认true,但是load()在调用setAttributes()没有传递$safeOnly参数,导致默认$safeOnly等于truesetAttributes()方法中有这样一句
$attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes());
入托$safeOnly = true 调用 $this->safeAttributes(),否则调用$this->attributes()
这两个方法应该都是返回当前model所定义的字段数组,但是$this->safeAttributes()始终为[],我试了一下$this->attributes()可以正常返回字段数组。所以解决办法:
在load()调用setAttributes()时,传递第二个参数$safeOnly为false,一共两处。$scope = $formName === null ? $this->formName() : $formName; if ($scope === '' && !empty($data)) { $this->setAttributes($data,false); return true; } elseif (isset($data[$scope])) { $this->setAttributes($data[$scope],false); return true; } else { return false; }
再测试成功了。 :)
我一直在使用Laravel这个框架,非常的好用,而且感觉非常专业bug极少(目前我还没遇到过)。我也是刚接触yii这个框架,第一天就卡在了这里,看着官方教程做的。瞬间对这个框架没什么信心了。
不是bug。首先load()方法是框架里面的方法,实际项目中不是你想改就可以该吧。
这里的问题在于:
safeAttributes()方法,$safeOnly参数为true的时候,是一种安全模式:
A safe attribute is one that is associated with a validation rule in the current [[scenario]].
意思就是说,安全模式下,要想更改一个属性的值,比如在models中设置rules规则。
我认为这是一种非常好的思想。想更改一个变量,必须先对变量设置一个规则,然后校验通过了再允许修改。