2016-07-15 57 views
0

我有一個Zend \ Session Manager和一個DbTableGateway來處理會話。我的代碼在another SO answer。但每當會話過期,我得到一個錯誤Fatal error: Maximum function nesting level of '100' reached, aborting! in [path]\vendor\zendframework\zend-db\src\Sql\AbstractExpression.php on line 40如何解決Zend DbTableGateway會話過期後讀取/銷燬無限循環?

我發現如何將xdebug嵌套級別更改爲200,但後來我也達到了200的限制。

Picture of the fatal error.

所以我之間DbTableGateway-()和無限循環>閱讀DbTableGateway-> destroy()方法。我注意到錯誤中引用的兩行都調用另一個方法,但它是Zend代碼,所以我不想改變它。

它只發生在會話過期後,而不是當我從數據庫中刪除包含會話信息的行時。在發生這種情況後,當我查看錶格時,我注意到除了數據列之外,表格中的行仍然存在。

id    name   modified lifetime data 
[random string] [session name] 1468587768 1440  - 

所以它看起來像read()方法檢查表包含ID和名稱列,並發現該行,然後調用destroy()方法,它調用read()。我怎樣才能解決這個問題?

在附註中,刷新頁面可以解決用戶的問題,但我不想讓用戶拋出異常並強制他們刷新頁面的代碼。

+0

你需要調查的是設置一個方法'destroy'數據,並嘗試用這個數據手動從數據庫中刪除行 – newage

+0

我沒有得到所有這些,但我調查了讀取和銷燬方法,並確認destroy()的第一件事確實是調用read(),然後read()檢查行在數據庫中,因爲它是,它會檢查第i行它過去了它的過期時間,因爲它是,它調用destroy(),啓動循環。這個問題一直存在,直到一個新的會話(帶有一個新的ID)被啓動,但這個有問題的行永遠不會從數據庫中刪除。我可以在測試時手動移除它們,但這不適用於成品。 – Miryafa

回答

0

這對我有效:創建一個擴展DbTableGateway並修改其destroy方法以檢查行是否存在而不是調用read()函數的類。然後使用該類而不是DbTableGateway。

因此,這裏的新存儲處理器類的代碼:

class MySessionSaveHandler extends DbTableGateway 
{ 
    /** 
    * Destroy session 
    * 
    * @param string $id 
    * @return bool 
    */ 
    public function destroy($id) 
    { 
     // I removed "read" to prevent an infinite loop, and am using the first line of "read" instead to check if the row exists 
     $rows = $this->tableGateway->select([ 
      $this->options->getIdColumn() => $id, 
      $this->options->getNameColumn() => $this->sessionName, 
     ]); 

     if (! (bool) $rows) { 
      return true; 
     } 

     return (bool) $this->tableGateway->delete([ 
      $this->options->getIdColumn() => $id, 
      $this->options->getNameColumn() => $this->sessionName, 
     ]); 
    } 
} 

這裏是你如何更換DbTableGateway:

/* @var $adapter \Zend\Db\Adapter\Adapter */ 
$adapter = $serviceManager->get('Zend\Db\Adapter\Adapter'); 
$tableGateway = new TableGateway('mytablename', $adapter); 
return new MySessionSaveHandler($tableGateway, new DbTableGatewayOptions());