sql >> Base de Datos >  >> RDS >> Mysql

PHP Guardando sesiones en la base de datos. El método de lectura no parece funcionar

Estás usando Codeigniter. Tiene la característica de almacenar sesiones en la base de datos ya incorporada.

Simplemente elimine su código que no funciona y use la función de Codeigniter en su lugar. Solo necesitas configurarlo.

Aparte de eso, si realmente quieres "quedarte con los tuyos", hay múltiples problemas con su código. Son fáciles de detectar si sigue los siguientes puntos:

  1. Lea sobre cada función de devolución de llamada para el controlador de guardado de sesión. Especialmente qué datos reciben y en qué formato (no hacerlo conduce a al menos un error que puede desencadenar el comportamiento que describe como "no funciona").
  2. Realice un registro de errores. Si tiene un problema con el controlador de guardado que genera errores, es posible que no se vean porque la salida al navegador ya no es posible. Esto requiere que registre los errores en el archivo. Esto es muy importante cuando soluciona problemas con un controlador de guardado de sesión.
  3. Quite el código de interacción de la base de datos. Esto también le permite proporcionar mejor información de error en caso de que falle la interacción con la base de datos (no hacerlo oculta al menos un error que puede resultar en el comportamiento que describe como "no funciona").
  4. Quite el código que no sea necesario. Quiero decir, no es necesario. Tener un código que no es necesario puede incluir errores que resultan en el escenario "no funciona" que tiene aquí. Así que te estás impidiendo hacer las cosas sin ningún motivo. Un ejemplo:ini_set("session.save_handler", "user"); - Mientras no tengas idea de lo que haces, no lo hagas. No hay un controlador de guardado predefinido llamado user en PHP, ni estás definiendo eso.

Y eso es básicamente todo. Entonces pude detectar dos errores reales que causan esto, los otros pasos son necesarios para que pueda lidiar con problemas futuros:

  1. Asegúrese de estar siempre relacionado con la misma tabla de base de datos. Por ejemplo, si escribe en la tabla MY_SESSIONS y leer de la tabla SESSIONS , esto nunca funcionará.
  2. Asegúrese de que los datos que le devuelva a PHP sean compatibles con los datos que espera. Por ejemplo, si almacena los datos codificados en Base64 en la base de datos y los devuelve a PHP codificados en Base64, no hay nada que PHP pueda hacer con esos datos.

Otros problemas potenciales que no son visibles desde su código:

  1. El esquema de la base de datos que tiene no se ajusta a los datos que almacena allí (no ha proporcionado el esquema de la tabla, por lo que no se puede decir si esto le causa problemas o no).
  2. El identificador del enlace de la base de datos podría cambiar porque el mismo codeigniter está creando una conexión a la base de datos. Esto podría conducir a posibles efectos secundarios. Proporcionar explícitamente el identificador de enlace para la conexión a la base de datos ayuda a tener un sueño relajado.
  3. Errores en consultas SQL que pasaron desapercibidos porque falta el manejo de errores para las partes de la base de datos.

Código de ejemplo:

ob_start();

session_name("test");
session_set_cookie_params(0, '/', '.test.com');

$s = new SessionManagement();
$s->register();

session_start();

ECHO $_SESSION['test'], "\n"; # value

SessionManagement refactorizado clase:

class SessionManagement
{
    private $_timeout;
    private $_db;

    public function __construct() {

        $CI =& get_instance();
        $CI->load->database();

        $this->_db = new LegacyMysqlDatabase(
            $CI->db->hostname, $CI->db->username, $CI->db->password, $CI->db->database
        );

        $this->_timeout = 60 * 60 * 10;
    }

    public function _open() {

        return TRUE;
    }

    public function _close() {

        return TRUE;
    }

    public function _read($session_id) {

        $db         = $this->_db;
        $session_id = $db->escape($session_id);
        $sql        = "SELECT session_data
            FROM   SESSION
            WHERE  session_id = '$session_id'";

        if (!($result = $db->query($sql)) || !$result->getNumberOfRows()) {
            return '';
        }

        $record = $result->fetchAssoc();
        return $record['session_data'];
    }

    public function _write($session_id, $session_data) {

        $db              = $this->_db;
        $session_id      = $db->escape($session_id);
        $session_data    = $db->escape($session_data);
        $session_expires = time() + $this->_timeout;

        $sql = "REPLACE INTO SESSION (session_id,    session_data,    session_expires)
                             VALUES  ('$session_id', '$session_data', $session_expires)";

        return (bool)$db->query($sql); // cast to bool because PHP would cast to int
    }

    public function _gc($max) {

        return TRUE;
    }

    public function _destroy($id) {

        $db         = $this->_db;
        $session_id = $db->escape($id);
        $sql        = "DELETE
                FROM   SESSION
                WHERE  session_id = '$id'";

        return $db->query($sql);
    }

    public function register() {

        $registered = session_set_save_handler(
            array($this, '_open'),
            array($this, '_close'),
            array($this, '_read'),
            array($this, '_write'),
            array($this, '_destroy'),
            array($this, '_gc')
        );
        if (!$registered) {
            throw new Exception('Can not register session savehandler.');
        }
    }
}

Código de interacción de base de datos con manejo de errores:

class LegacyMysqlDatabase
{
    private $_hostname;
    private $_username;
    private $_password;
    private $_database;

    private $_link;
    private $_initError = false;

    public function __construct($hostname, $username, $password, $database) {

        $this->_hostname = $hostname;
        $this->_username = $username;
        $this->_password = $password;
        $this->_database = $database;
    }

    public function query($sql) {

        $link   = $this->getLink();
        $result = mysql_query($sql, $link);
        if ($result === false) {
            trigger_error(sprintf('Query "%s" failed: #%d: %s', $sql, mysql_errno($link), mysql_error($link)));
            throw new Exception('Failed to query Mysql database.');
        }
        return new LegacyMysqlResult($result);
    }

    public function escape($string) {

        return mysql_real_escape_string($string, $this->getLink());
    }

    private function getLink() {

        if ($this->_initError) {
            throw new Exception('Failed to initialize the database.');
        }

        if ($this->_link === null) {
            $this->_initError = true;
            $result           = mysql_connect($this->_hostname, $this->_username, $this->_password);
            if (!$result) {
                throw new Exception('Can not connect to Mysql database.');
            }
            $this->_link = $result;
            $selected    = mysql_select_db($this->_database, $this->_link);
            if (!$selected) {
                trigger_error(sprintf('Can not select Mysql database "%s": #%d: %s', $this->_database, mysql_errno($result), mysql_error($result)));
                throw new Exception(sprintf('Can not select Mysql database "%"', $this->_database));
            }
            $this->_initError = false;
        }
        return $this->_link;
    }
}

class LegacyMysqlResult
{

    private $_result;

    public function __construct($result) {

        $this->_result = $result;
    }

    public function getNumberOfRows() {

        return mysql_num_rows($this->_result);
    }

    public function fetchAssoc() {

        return mysql_fetch_assoc($this->_result);
    }
}