Mysql
 sql >> Database >  >> RDS >> Mysql

PHP Salvataggio delle sessioni nel database. Il metodo di lettura non sembra funzionare

Stai usando Codeigniter. Ha la funzione di memorizzare le sessioni nel database già integrato.

Basta rimuovere il codice che non funziona e utilizzare invece la funzione di Codeigniter. Devi solo configurarlo.

A parte questo, se vuoi davvero "stare con te", ce ne sono molti problemi con il tuo codice. Sono facili da individuare se segui i seguenti punti:

  1. Leggi ogni funzione di callback per il gestore di salvataggio della sessione. Soprattutto quali dati ricevono e in quale formato (non farlo comporta almeno un errore in grado di innescare il comportamento che descrivi come "non funzionante").
  2. Esegui la registrazione degli errori. Avere un problema con il gestore di salvataggio che porta a fornire errori potrebbe lasciarli invisibili perché l'output sul browser non è più possibile. Ciò richiede di registrare gli errori su file. Questo è molto importante quando risolvi i problemi con un gestore di salvataggio della sessione.
  3. Sposta via il codice di interazione del database. Ciò ti consente anche di fornire migliori informazioni sull'errore nel caso in cui l'interazione con il database fallisca (non farlo nasconde almeno un errore che può provocare il comportamento che descrivi come "non funzionante").
  4. Rimuovi il codice non necessario. Voglio dire, non è necessario. Avere codice non necessario può includere errori che risultano nello scenario "non funzionante" che hai qui. Quindi ti stai ostacolando dal portare a termine le cose senza motivo. Un esempio:ini_set("session.save_handler", "user"); - finché non hai idea di cosa fai, non farlo. Non esiste un gestore di salvataggio predefinito chiamato user in PHP, né lo stai definendo.

E questo è fondamentalmente. Quindi ho potuto individuare due veri errori che causano questo, gli altri passaggi sono necessari in modo da poter affrontare problemi futuri:

  1. Assicurati di essere sempre correlato alla stessa tabella del database. Ad esempio, se scrivi nella tabella MY_SESSIONS e leggi dalla tabella SESSIONS , non funzionerà mai.
  2. Assicurati che i dati che restituisci a PHP siano compatibili con i dati che si aspetta. Ad esempio, se memorizzi i dati Base64 codificati nel database e li restituisci a PHP Base64 codificati, non c'è nulla che PHP possa fare con quei dati.

Altri potenziali problemi che non sono visibili dal tuo codice:

  1. Lo schema del database che hai non è adatto ai dati che memorizzi (non hai fornito lo schema della tabella, quindi non si può dire se questo ti causa problemi).
  2. L'identificatore del collegamento al database potrebbe cambiare perché codeigniter stesso sta creando una connessione al database. Ciò potrebbe portare a potenziali effetti collaterali. Fornire esplicitamente l'identificatore di collegamento per la connessione al database aiuta a dormire sonni tranquilli.
  3. Errori nelle query SQL che sono passati inosservati perché manca la gestione degli errori per le parti del database.

Codice di esempio:

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 rifattorizzato classe:

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.');
        }
    }
}

Codice di interazione del database con gestione degli errori:

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