我的表单存在问题,其中包含许多动态创建的表单元素以及附加的Server-Actions。经过几次回发后,我得到了一个致命的内存耗尽错误。 QForm的Serialize方法消耗了大量的兆字节似乎表单状态随着每个回发而增长,直到它如此之大,即serialize()抛出致命的内存耗尽错误。为什么会增长?表单元素的数量总是相同的......
有任何建议吗?
提前,
扬
答案 0 :(得分:0)
我想问题不在于FormState的增长。我认为会议的成长。问题是 - 当您继续进行回发或打开新页面时,会创建一个新的FormState。此FormState保存在PHP会话中(您使用的是QSessionFormStateHandler)。在某个时间点,所有FormStates的总大小可能会变得非常大,以至于PHP无法在会话数据中处理它。这是因为PHP有一个限制每个脚本运行/请求将消耗的内存量的设置(这是一件好事)。
大多数情况下,PHP会通过报告内存耗尽来抱怨它。发生这种情况的原因是:当您运行/调用脚本时,会发生以下事情:
在您的情况下,会话数据将继续增长,直到它开始消耗足够的内存,PHP无法工作在设置的内存约束内分配新变量(第3步失败)。
您有两种解决方案:
使用另一个FormStateHandler。我建议使用QDbBackedFormStateHandler来保持文件系统的清洁。使用另一个FormStateHandler可确保您的会话数据与FormState数据分开,并且所有FormStates都单独保存(在文件中或作为单独的DB条目),并确保在会话中不收集无用的FormStates。
增加PHP的每脚本内存限制。 不推荐使用此解决方案,您只能将其用作临时解决方案。
此外,在某些情况下,您可能会在表单中声明一个临时变量,或者其中一个子控件继续增长。考虑一下:
<?php
// We are inside the definition of a control/panel/form
$this->arrObj_TempEntries = array();
// ... using the above variable somewhere inside an event handler:
public function btnRefreshHandler($strFormId, $strControlId, $strParameter) {
// Assume $arrObj_NewEntries is already populated with some objects
foreach($arrObj_NewEntries as $objNewEntry){
array_push($this->arrObj_TempEntries, $objNewEntry);
}
}
// ... rest of the stuff
?>
在这种情况下,$this->arrObj_TempEntries
的值将继续增加,因为旧条目未被清除并导致非常大的FormState,并最终导致页面崩溃。如果对象是控件,那就更大了。
我希望这会有所帮助。