2016-07-15 11 views
0

Ich habe einen Zend \ Session Manager mit einem DbTableGateway, um Sitzungen zu behandeln. Mein Code ist in another SO answer. Aber jedes Mal, wenn die Sitzung abläuft, erhalte ich einen Fehler Fatal error: Maximum function nesting level of '100' reached, aborting! in [path]\vendor\zendframework\zend-db\src\Sql\AbstractExpression.php on line 40Wie repariert man Zend DbTableGateway Endlosschleife nach Ablauf der Sitzung lesen/zerstören?

Ich fand heraus, wie die Verschachtelung Ebene xdebug auf 200 ändern, aber dann habe ich auch die 200 Grenze erreicht.

Picture of the fatal error.

So habe ich eine Endlosschleife zwischen DbTableGateway-> read() und DbTableGateway-> destroy(). Ich bemerkte, dass die 2 Zeilen, auf die im Fehler verwiesen wird, die andere Methode aufrufen, aber es ist Zend Code, also möchte ich es nicht ändern.

Es passiert nur, nachdem die Sitzung abläuft, und nicht, wenn ich die Zeile mit den Sitzungsinformationen aus der Datenbank entfernen. Als ich nach dem Auftauchen auf den Tisch schaute, bemerkte ich, dass die Zeile mit Ausnahme der Datenspalte immer noch in der Tabelle vorhanden ist.

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

So sieht es aus wie das Lesen() -Methode überprüft die Tabelle nach einer Zeile die ID und den Namen enthält, und findet diese Reihe, ruft dann zerstören(), die lesen() aufruft. Wie kann ich das beheben?

Nebenbei, das Aktualisieren der Seite löst das Problem für den Benutzer, aber ich möchte keinen Code haben, der eine Ausnahme beim Benutzer auslöst und sie zwingt, die Seite zu aktualisieren.

+0

Sie benötigen Daten zu untersuchen, die sich auf ein Verfahren 'destroy' setzen und versuchen, Entferne Zeile aus der Datenbank manuell mit diesen Daten – newage

+0

Ich habe nicht alles bekommen, aber ich untersuchte die Lese - und Zerstörungsmethode und bestätigte, dass in der Tat das erste, was destroy() tut, read() aufruft, und dann read() prüft, ob Zeile ist in der Datenbank, und weil es ist, überprüft es, ob die Zeile i s nach seiner abgelaufenen Zeit, und weil es ist, ruft es destroy() auf und initiiert die Schleife. Dieses Problem bleibt bestehen, bis eine neue Sitzung (mit einer neuen ID) gestartet wird, die betreffende Zeile jedoch nie aus der Datenbank entfernt wird. Ich kann sie beim Testen manuell entfernen, aber das ist keine Option für ein fertiges Produkt. – Miryafa

Antwort

0

Das funktionierte für mich: Erstellen Sie eine Klasse, die DbTableGateway erweitert und seine Methode destroy ändert, um zu überprüfen, ob eine Zeile vorhanden ist, anstatt die Funktion read() aufzurufen. Verwenden Sie dann diese Klasse anstelle von DbTableGateway.

Also hier ist der Code für den neuen Handler-Klasse sparen:

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, 
     ]); 
    } 
} 

Und hier ist, wie Sie DbTableGateway ersetzen:

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