2012-08-08 25 views
5

Después de una gran cantidad de depuración, parece que el problema (vergonzosamente) en mi código de sesión de base de datos no es un problema de sesión típico. Se puede ver mi respuesta relacionándola here - GraciasDatos de sesión eliminados en session_start() después de la redirección de página


Entiendo que esto puede ser un duplicado de preguntas similares (por ejemplo one, two, three), pero a pesar de seguir lo que parece ser las mejores prácticas de este I' Todavía tengo problemas.

Al usar session_set_save_handler() para usar mi clase de sesión de base de datos, los datos de la sesión se borran cuando la sesión comienza en session2.php después de ser redirigido desde session1.php.

Una visión general de mis observaciones:

  • Los datos se guardan en la base de datos correctamente en session1.php
  • de datos se pierde en session_start() en session2.php
  • de datos todavía está en la base de datos después de se llama a la redirección y antes de session_start() en session2.php
  • ID de sesión sigue siendo el mismo y se almacena en una cookie que se envía de nuevo al servidor en los encabezados de solicitud correctamente
  • Uso de la sesión por defecto de PHP manejo funciona bien

Y nota:

  • exit() se utiliza después de la cabecera()
  • session_start() en cada página antes de la salida

Tener Hice un error tipográfico tonto? Hecho un error tonto? ¿O es esto una extraña peculiaridad?

Gracias de antemano por cualquier ayuda ofrecida.

Aquí está el código (extraído en archivos de prueba, mientras que la fijación de este tema):

session1.php

<?php 

require_once('session.php'); 

session_start(); 

$_SESSION['KEY'] = 'VALUE PHPSESSID: ' . session_id(); 

session_write_close(); 
header('Location: session2.php'); 
exit; 

session2.php

<?php 

require_once('session.php'); 

session_start(); 

// Nothing? 
var_dump($_SESSION); 

session.php

<?php 

define("DB_HOST", 'localhost'); 
define("DB_USER", '******'); 
define("DB_PWD", '******'); 
define("DB_NAME", '******'); 

require_once('class/DatabaseSessionHandler.php'); 

// Use the DatabaseSessionHandler class to handle sessions 
$session_handler = new DatabaseSessionHandler; 
// Set up the handler above as the default session handler 
session_set_save_handler(
    array($session_handler, 'open'), 
    array($session_handler, 'close'), 
    array($session_handler, 'read'), 
    array($session_handler, 'write'), 
    array($session_handler, 'destroy'), 
    array($session_handler, 'gc') 
); 

DatabaseSessionHandler.php

<?php 

class DatabaseSessionHandler 
{ 

    protected $connection; 
    protected $session_life_time; 

    public function __construct() 
    { 
     // Ensure that everything is closed correctly as 
     // per warning on http://uk3.php.net/session_set_save_handler 
     register_shutdown_function('session_write_close'); 
    } 

    public function open($save_path, $session_name) 
    { 
     $this->connection = new mysqli(DB_HOST, DB_USER, DB_PWD, DB_NAME); 
     $this->session_life_time = get_cfg_var("session.gc_maxlifetime"); 

     if ($this->connection->connect_error) 
      return false; 

     return true; 
    } 

    public function close() 
    { 
     $this->connection->close(); 
     return true; 
    } 

    public function read($session_id) 
    { 
     $data = ''; 

     $statement = $this->connection->prepare("SELECT `session_data` 
                FROM `session` 
                WHERE `session_id` = ? "); 
     $statement->bind_param("s", $session_id); 
     $statement->execute(); 
     $statement->bind_result($data); 

     return (string) $data; 
    } 

    public function write($session_id, $session_data) 
    { 
     $expiry_time = time() + $this->session_life_time; 
     $statement = $this->connection->prepare("REPLACE INTO `session` 
               (`session_id`, `session_data`, 
               `expiry_time`) 
               VALUES (?, ?, ?)"); 
     $statement->bind_param("ssi", $session_id, $session_data, $expiry_time); 

     if (!$statement->execute()) 
      return false; 

     return true; 
    } 

    public function destroy($session_id) 
    { 
     $statement = $this->connection->prepare("DELETE FROM `session` 
                WHERE `session_id` = ?"); 
     $statement->bind_param("s", $session_id); 

     if (!$statement->execute()) 
      return false; 

     return true; 
    } 

    public function gc($max_lifetime) 
    { 
     $current_time = time(); 
     $statement = $this->connection->prepare("DELETE FROM `session` 
                WHERE `expiry_time` < ?"); 
     $statement->bind_param("i", $current_time); 

     if (!$statement->execute()) 
      return false; 

     return true; 
    } 

} 
+2

registra algo en destroy, y algo más en gc, para que sepas cuál es el responsable de la eliminación. O usa un depurador – greg0ire

+0

¿Qué sucede si lo prueba sin el 'session_write_close();'? Además, ¿en qué servidor estás ejecutando esto? Vea esta pregunta (vea los comentarios en la respuesta) http://stackoverflow.com/questions/10028643/php-session-data-not-being-stored-simply –

+0

@GeraldVersluis los datos todavía están en la base de datos después de la redirección y por lo tanto no es la función session_write_close() (intenté eliminarla y todavía no tuve suerte) – Skyrail

Respuesta

0

Bueno, después de un amplio registro de archivos e impresión de las variables (algunas de las funciones de sesión son llamados después de la salida al navegador se envía y, como tal, no se pueden generar errores de la manera normal) resulta que el problema fue con mi código de sesión de la base de datos.

Olvidé agregar '$ statement-> fetch()' después de vincular la salida MySQLi a una variable y, como tal, nunca obtuve los datos de la base de datos.

Un error vergonzoso pero que sirvió para volver a casa con el hecho de que si hay algo mal con su software, la mayoría de las veces es un problema en su código y no en el idioma o bibliotecas que está utilizando.

Gracias a quienes comentaron y respondieron, he aprendido mucho sobre las sesiones de PHP en los últimos días debido a esto.

2

están limpiando los datos de sesión a menos de hora actual.debe ser la hora actual - max_lifetime

Aquí está la solución

public function gc($max_lifetime) 
{ 
    $current_time = time() - $max_lifetime; 
    $statement = $this->connection->prepare("DELETE FROM `session` 
                WHERE `expiry_time` < ?"); 
    $statement->bind_param("i", $current_time); 

    if (!$statement->execute()) 
      return false; 

    return true; 
} 
+0

Ah, eso fue un problema Lo había pasado por alto pero no parece ser el problema. El problema ocurre incluso cuando el recolector de basura no recibe una llamada. Le agradezco que lo haya corregido, ya que, de otro modo, lo más probable es que haya pasado por alto. – Skyrail

Cuestiones relacionadas