2012-09-04 2 views
7

Hier ist die Sache. Ein Kollege von mir versucht, die Sitzungsbehandlung eines von uns verwendeten Frameworks zu überschreiben. Dieses Framework verwendet standardmäßig die eigene native Session-Handhabung von PHP, aber er versucht nun, eine Datenbankschicht zwischen den Anfragen zu implementieren.Hier ist eine echte Herausforderung: Warum ruft PHP die Shutdown-Funktion auf, bevor Sitzungen geschrieben werden?

Problem ist, dass das Datenbankobjekt nicht verfügbar ist, wenn Sitzungen nicht mehr geschrieben werden. Es ist jedoch für andere Funktionen verfügbar, z. B. wenn Daten aus Sitzungen gelesen werden. Dies ist ein wildes Verhalten. Hier ist, was wir haben:

register_shutdown_function('exithandler'); 

session_set_save_handler(
    'sess_open', 
    'sess_close', 
    'sess_read', 
    'sess_write', 
    'sess_destroy', 
    'sess_gc' 
); 

Jede dieser Funktionen schreibt auch nur eine einzige Zeile in unsere Protokolldatei, die wir mit dem Namen der Funktion verfolgen können. Dies geschieht immer dann, wenn die Funktion aufgerufen wird. Nun sind hier zwei URLs gefragt, die erste, wo Sitzungen tatsächlich geschrieben werden (neue Daten zu den Sitzungen) und die zweite, wo Sitzungsdaten gerade überprüft werden (und keine wird geschrieben). Hier ist das Puzzle:

/login/ 
sess_open 
sess_read 
exithandler 
sess_write 
sess_close 

/account/ 
sess_open 
sess_read 
sess_write 
sess_close 
exithandler 

Warum ist dieses Verhalten anders? Warum wird der Exit-Handler aufgerufen, bevor Daten in Sitzungen gespeichert werden und warum gilt das nicht für eine normale Seite, obwohl die gleichen Methoden tatsächlich aufgerufen werden?

Problem ist, dass keine unserer Klassen mehr verfügbar sind, nachdem der exithandler aufgerufen wurde, ich nehme an, dass PHP Garbage Collector __destruct() -Methoden für alle unsere Klassen aufgerufen hat und sie weg sind. Das ist einfach schlecht.

Wer weiß, warum PHP sich so verhält?

+1

Welche Version von PHP verwenden Sie? –

+0

Ich habe dies mit PHP 5.4 getestet, und ich kann nur die erste Reihenfolge der Operationen für beide Arten von Anfragen reproduzieren: Sitzungsdaten lesen und schreiben. – nickb

+1

Es gibt ein häufiges Problem mit einer PHP-Version, bei der Sie vor dem Aufruf von 'session_set_save_handler()' eine Zeile hinzufügen müssen. Verwenden Sie zuerst: 'register_shutdown_function ('session_write_close')' und sehen Sie, ob das Ihr instabiles Verhalten behebt. –

Antwort

2

Wie Ihre Kommentare PHP5.4 sagen, sollten Sie einen Blick auf die SessionHandlerInterface() werfen. Sie können die register_shutdown_function in der open() Methode übergeben, um den Prozess zu halbieren und die Vorteile von PHP5.4 wirklich zu nutzen.

<?php 
class MySessionHandler implements SessionHandlerInterface 
{ 
    private $savePath; 

    public function open($savePath, $sessionName) 
    { 
     register_shutdown_function('session_write_close'); 
     $this->savePath = $savePath; 
     if (!is_dir($this->savePath)) { 
      mkdir($this->savePath, 0777); 
     } 

     return true; 
    } 

    public function close() 
    { 
     return true; 
    } 

    public function read($id) 
    { 
     return (string)@file_get_contents("$this->savePath/sess_$id"); 
    } 

    public function write($id, $data) 
    { 
     return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true; 
    } 

    public function destroy($id) 
    { 
     $file = "$this->savePath/sess_$id"; 
     if (file_exists($file)) { 
      unlink($file); 
     } 

     return true; 
    } 

    public function gc($maxlifetime) 
    { 
     foreach (glob("$this->savePath/sess_*") as $file) { 
      if (filemtime($file) + $maxlifetime < time() && file_exists($file)) { 
       unlink($file); 
      } 
     } 

     return true; 
    } 
} 

$handler = new MySessionHandler(); 
session_set_save_handler($handler, true); 
session_start(); 
+0

Leider benötigt mein Framework PHP 5.3 und ich habe einen benutzerdefinierten Session-Handler erstellt, der für meine Bedürfnisse besser geeignet war. Aber Ihre Antwort ist technisch eine "richtige Antwort", obwohl PHP 5.4 funktioniert. – kingmaple

+0

Funktioniert register_shutdown_handler() gut in Klassen? –

Verwandte Themen