sql >> Database >  >> RDS >> Mysql

PHP Sessies opslaan in de database. Leesmethode lijkt niet te werken

Je gebruikt Codeigniter. Het heeft de mogelijkheid om sessies op te slaan in de reeds ingebouwde database.

Verwijder gewoon uw code die niet werkt en gebruik in plaats daarvan de functie van Codeigniter. U hoeft het alleen maar te configureren.

Afgezien daarvan, als je echt "bij de jouwe wilt blijven", zijn er meerdere problemen met uw code. Ze zijn gemakkelijk te herkennen als u de volgende punten volgt:

  1. Lees over elke callback-functie voor de handler voor het opslaan van sessies. Vooral welke gegevens ze ontvangen en in welk formaat (niet doen leidt tot ten minste één fout die het gedrag kan activeren dat u beschrijft als "niet werkend").
  2. Voer foutenregistratie uit. Als u een probleem heeft met de opslaghandler dat tot fouten leidt, kan het zijn dat deze ongezien blijven omdat uitvoer naar de browser niet langer mogelijk is. Dit vereist dat u fouten in het bestand registreert. Dit is erg belangrijk wanneer je problemen oplost met een session savehandler.
  3. Verplaats de database-interactiecode uit de weg. Hierdoor kunt u ook betere foutinformatie verstrekken in het geval dat de database-interactie mislukt (als u dit niet doet, wordt ten minste één fout verborgen die kan resulteren in het gedrag dat u beschrijft als "niet werkend").
  4. Verwijder code die niet nodig is. Ik bedoel, het is niet nodig. Het hebben van code die niet nodig is, kan fouten bevatten die resulteren in het "niet-werkende" scenario dat u hier hebt. Dus je belemmert jezelf om dingen gedaan te krijgen zonder reden. Een voorbeeld:ini_set("session.save_handler", "user"); - zolang je geen idee hebt wat je doet, doe het dan niet. Er is geen vooraf gedefinieerde savehandler genaamd user in PHP, en je definieert die ook niet.

En dat is het in principe. Dus ik kon twee echte fouten ontdekken die dit veroorzaken, de andere stappen zijn nodig zodat je toekomstige problemen kunt oplossen:

  1. Zorg ervoor dat u altijd gerelateerd bent aan dezelfde databasetabel. Als u bijvoorbeeld in tabel MY_SESSIONS . schrijft en lees uit tabel SESSIONS , dit zal nooit werken.
  2. Zorg ervoor dat de gegevens die u teruggeeft aan PHP compatibel zijn met de verwachte gegevens. Als u bijvoorbeeld de Base64-gecodeerde gegevens in de database opslaat en deze teruggeeft aan PHP Base64-gecodeerd, kan PHP niets met die gegevens doen.

Andere mogelijke problemen die niet zichtbaar zijn in uw code:

  1. Het databaseschema dat u heeft, past niet bij de gegevens die u daarin opslaat (u heeft het tabelschema niet opgegeven, dus er kan niet worden gezegd of dit problemen oplevert).
  2. De databaselink-ID kan veranderen omdat codeigniter zelf een databaseverbinding maakt. Dit kan leiden tot mogelijke bijwerkingen. Het expliciet verstrekken van de link-ID voor de databaseverbinding helpt voor een ontspannen slaap.
  3. Fouten in SQL-query's die onopgemerkt zijn gebleven omdat de foutafhandeling voor de database-onderdelen ontbreekt.

Voorbeeldcode:

ob_start();

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

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

session_start();

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

Refactored SessionManagement klas:

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

Database-interactiecode met foutafhandeling:

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


  1. Een float selecteren in MySQL

  2. Een andere manier om automatische updates van statistieken te bekijken

  3. Hoe MySQL Root-wachtwoord opnieuw in te stellen

  4. Gegevens kopiëren van de ene tabel naar de andere in SQL