我对包含许多带有附加服务器操作的动态创建的表单元素的表单有疑问。经过几次回发后,我得到了一个致命的内存耗尽错误。QForm 的 Serialize 方法消耗大量兆字节似乎表单状态随着每次回发而增长,直到它变得如此之大,以至于 serialize() 抛出致命的内存耗尽错误。为什么它在增长?表单元素的数量总是一样的......
有什么建议吗?
提前谢谢,
简
我想问题不在于 FormState 增长了。我认为这是增长的会话。问题是 - 当您继续进行回发或打开新页面时,会创建一个新的 FormState。这个 FormState 保存在您的 PHP 会话中(您正在使用 QSessionFormStateHandler)。在某个时间点,所有 FormState 的总大小可能会变得如此之大,以至于 PHP 将无法在会话数据中处理它。发生这种情况是因为 PHP 有一个设置,它限制每个脚本运行/请求将消耗的内存量(这是一件好事)。
大多数时候,PHP 会通过报告内存耗尽来抱怨它。发生这种情况的原因是:当您运行/调用脚本时,会发生以下情况:
在您的情况下,会话数据将继续增长,直到它开始消耗足够的内存,PHP 无法在设置的内存限制内分配新变量(第 3 步失败)。
你有两个解决方案:
使用另一个 FormStateHandler。我建议使用 QDbBackedFormStateHandler 来保持文件系统清洁。使用另一个 FormStateHandler 可确保您的会话数据与您的 FormState 数据分开,并且所有 FormStates 都单独保存(在文件中或作为单独的数据库条目),并确保不会在您的会话中收集无用的 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 并最终导致页面崩溃。如果对象是控件,这是一个更大的问题。
我希望这有帮助。