Mysql
 sql >> Datenbank >  >> RDS >> Mysql

PHP Sessions in der Datenbank speichern. Read-Methode scheint nicht zu funktionieren

Sie verwenden Codeigniter. Es hat die Funktion, Sitzungen in der bereits integrierten Datenbank zu speichern.

Entfernen Sie einfach Ihren nicht funktionierenden Code und verwenden Sie stattdessen die Funktion von Codeigniter. Sie müssen es nur konfigurieren.

Abgesehen davon, wenn du wirklich "bei deinem bleiben willst", gibt es mehrere Probleme mit Ihrem Code. Sie sind leicht zu erkennen, wenn Sie die folgenden Punkte beachten:

  1. Lesen Sie mehr über jede Callback-Funktion für den Session-Save-Handler. Insbesondere welche Daten sie in welchem ​​Format erhalten (andernfalls führt dies zu mindestens einem Fehler, der das von Ihnen als „funktioniert nicht“ beschriebene Verhalten auslösen kann).
  2. Führen Sie eine Fehlerprotokollierung durch. Ein Problem mit dem Save-Handler, das zu Fehlern führt, kann diese unbemerkt lassen, da die Ausgabe an den Browser nicht mehr möglich ist. Dazu müssen Sie Fehler in einer Datei protokollieren. Dies ist sehr wichtig, wenn Sie Probleme mit einem Session-Savehandler beheben.
  3. Schieben Sie den Datenbankinteraktionscode aus dem Weg. Auf diese Weise können Sie auch bessere Fehlerinformationen bereitstellen, falls die Datenbankinteraktion fehlschlägt (andernfalls wird mindestens ein Fehler ausgeblendet, der zu dem Verhalten führen kann, das Sie als "funktioniert nicht" beschreiben).
  4. Entfernen Sie Code, der nicht benötigt wird. Ich meine, es ist nicht nötig. Code, der nicht benötigt wird, kann Fehler enthalten, die zu dem „nicht funktionierenden“ Szenario führen, das Sie hier haben. Sie hindern sich also daran, Dinge ohne Grund zu erledigen. Ein Beispiel:ini_set("session.save_handler", "user"); - Solange du keine Ahnung hast, was du tust, tu es nicht. Es gibt keinen vordefinierten Savehandler namens user in PHP, noch definieren Sie dieses.

Und das ist es im Grunde. Ich konnte also zwei echte Fehler erkennen, die dies verursachen, die anderen Schritte sind notwendig, damit Sie zukünftige Probleme lösen können:

  1. Stellen Sie sicher, dass Sie sich immer auf dieselbe Datenbanktabelle beziehen. Zum Beispiel, wenn Sie in die Tabelle MY_SESSIONS schreiben und aus der Tabelle SESSIONS lesen , das wird niemals funktionieren.
  2. Stellen Sie sicher, dass die Daten, die Sie an PHP zurückgeben, mit den erwarteten Daten kompatibel sind. Wenn Sie beispielsweise die Daten Base64-kodiert in der Datenbank speichern und sie Base64-kodiert an PHP zurückgeben, kann PHP nichts mit diesen Daten anfangen.

Andere potenzielle Probleme, die aus Ihrem Code nicht ersichtlich sind:

  1. Das Datenbankschema, das Sie haben, passt nicht zu den Daten, die Sie darin speichern (Sie haben das Tabellenschema nicht angegeben, daher kann nicht gesagt werden, ob dies Probleme verursacht oder nicht).
  2. Die Datenbankverbindungskennung kann sich ändern, da Codeigniter selbst eine Datenbankverbindung herstellt. Dies könnte zu möglichen Nebenwirkungen führen. Die explizite Angabe der Linkkennung für die Datenbankanbindung verhilft zu einem entspannten Schlaf.
  3. Fehler in SQL-Abfragen, die unbemerkt geblieben sind, weil die Fehlerbehandlung für die Datenbankteile fehlt.

Beispielcode:

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 umgestaltet Klasse:

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

Datenbankinteraktionscode mit Fehlerbehandlung:

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