Mysql
 sql >> Base de données >  >> RDS >> Mysql

PHP Enregistrement des sessions dans la base de données. La méthode de lecture ne semble pas fonctionner

Vous utilisez Codeigniter. Il a la fonctionnalité de stocker des sessions dans la base de données déjà intégrée.

Supprimez simplement votre code qui ne fonctionne pas et utilisez la fonctionnalité de Codeigniter à la place. Il vous suffit de le configurer.

A part ça, si vous voulez vraiment "rester avec les vôtres", il y en a plusieurs problèmes avec votre code. Ils sont faciles à repérer si vous suivez les points suivants :

  1. En savoir plus sur chaque fonction de rappel pour le gestionnaire de sauvegarde de session. Surtout quelles données ils reçoivent et dans quel format (ne pas le faire entraîne au moins une erreur capable de déclencher le comportement que vous décrivez comme "ne fonctionne pas").
  2. Établissez une journalisation des erreurs. Avoir un problème avec le gestionnaire de sauvegarde qui conduit à donner des erreurs peut les laisser invisibles car la sortie vers le navigateur n'est plus possible. Cela vous oblige à consigner les erreurs dans le fichier. Ceci est très important lorsque vous résolvez des problèmes avec un gestionnaire de sauvegarde de session.
  3. Éloignez le code d'interaction de la base de données. Cela vous permet également de fournir de meilleures informations sur les erreurs en cas d'échec de l'interaction avec la base de données (ne pas le faire masque au moins une erreur susceptible d'entraîner le comportement que vous décrivez comme "ne fonctionne pas").
  4. Supprimez le code qui n'est pas nécessaire. Je veux dire, ce n'est pas nécessaire. Avoir du code qui n'est pas nécessaire peut inclure des erreurs qui entraînent le scénario "ne fonctionne pas" que vous avez ici. Vous vous empêchez donc de faire avancer les choses sans raison. Un exemple :ini_set("session.save_handler", "user"); - Tant que vous n'avez aucune idée de ce que vous faites, ne le faites pas. Il n'y a pas de savehandler prédéfini appelé user en PHP, et vous ne définissez pas non plus celui-là.

Et c'est fondamentalement ça. J'ai donc pu repérer deux erreurs réelles à l'origine de cela, les autres étapes sont nécessaires pour que vous puissiez gérer les problèmes futurs :

  1. Assurez-vous de toujours vous référer à la même table de base de données. Par exemple, si vous écrivez dans la table MY_SESSIONS et lire à partir de la table SESSIONS , cela ne fonctionnera jamais.
  2. Assurez-vous que les données que vous renvoyez à PHP sont compatibles avec les données qu'il attend. Par exemple, si vous stockez les données encodées en Base64 dans la base de données et que vous les restituez à PHP encodées en Base64, il n'y a rien que PHP puisse faire avec ces données.

Autres problèmes potentiels qui ne sont pas visibles depuis votre code :

  1. Le schéma de la base de données que vous avez n'est pas adapté aux données que vous y stockez (vous n'avez pas fourni le schéma de la table, il est donc impossible de dire si cela vous pose problème ou non).
  2. L'identifiant du lien de la base de données peut changer car codeigniter lui-même crée une connexion à la base de données. Cela pourrait entraîner des effets secondaires potentiels. Fournir explicitement l'identifiant du lien pour la connexion à la base de données aide à dormir détendue.
  3. Erreurs dans les requêtes SQL qui sont passées inaperçues car la gestion des erreurs pour les parties de la base de données est manquante.

Exemple de code :

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

Code d'interaction de la base de données avec gestion des erreurs :

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