QForm:序列化在几次回发后耗尽内存

时间:2015-01-08 09:40:15

标签: php qcubed

我的表单存在问题,其中包含许多动态创建的表单元素以及附加的Server-Actions。经过几次回发后,我得到了一个致命的内存耗尽错误。 QForm的Serialize方法消耗了大量的兆字节似乎表单状态随着每个回发而增长,直到它如此之大,即serialize()抛出致命的内存耗尽错误。为什么会增长?表单元素的数量总是相同的......

有任何建议吗?

提前,

1 个答案:

答案 0 :(得分:0)

我想问题不在于FormState的增长。我认为会议的成长。问题是 - 当您继续进行回发或打开新页面时,会创建一个新的FormState。此FormState保存在PHP会话中(您使用的是QSessionFormStateHandler)。在某个时间点,所有FormStates的总大小可能会变得非常大,以至于PHP无法在会话数据中处理它。这是因为PHP有​​一个限制每个脚本运行/请求将消耗的内存量的设置(这是一件好事)。

大多数情况下,PHP会通过报告内存耗尽来抱怨它。发生这种情况的原因是:当您运行/调用脚本时,会发生以下事情:

  1. PHP最初加载用户会话信息。
  2. PHP继续执行脚本。
  3. PHP执行命令并在需要时继续分配更多内存。
  4. PHP结束执行
  5. 在您的情况下,会话数据将继续增长,直到它开始消耗足够的内存,PHP无法工作在设置的内存约束内分配新变量(第3步失败)。

    您有两种解决方案:

    1. 使用另一个FormStateHandler。我建议使用QDbBackedFormStateHandler来保持文件系统的清洁。使用另一个FormStateHandler可确保您的会话数据与FormState数据分开,并且所有FormStates都单独保存(在文件中或作为单独的DB条目),并确保在会话中不收集无用的FormStates。

    2. 增加PHP的每脚本内存限制。 不推荐使用此解决方案,您只能将其用作临时解决方案。

    3. 此外,在某些情况下,您可能会在表单中声明一个临时变量,或者其中一个子控件继续增长。考虑一下:

      <?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,并最终导致页面崩溃。如果对象是控件,那就更大了。

      我希望这会有所帮助。