Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

PHP Salvando sessões no banco de dados. O método de leitura parece não funcionar


Você está usando o Codeigniter. Ele tem o recurso de armazenar sessões no banco de dados já embutido.

Basta remover seu código que não funciona e usar o recurso do Codeigniter. Você só precisa configurá-lo.

Além disso, se você realmente quer "ficar com os seus", existem vários problemas com seu código. Eles são fáceis de detectar se você seguir os seguintes pontos:
  1. Leia sobre cada função de retorno de chamada para o manipulador de salvamento de sessão. Especialmente quais dados eles recebem e em qual formato (não fazer isso leva a pelo menos um erro capaz de desencadear o comportamento que você descreve como "não está funcionando").
  2. Faça o registro de erros. Ter um problema com o manipulador de salvamento que leva a erros pode deixá-los invisíveis porque a saída para o navegador não é mais possível. Isso requer que você registre erros no arquivo. Isso é muito importante ao solucionar problemas com um manipulador de salvamento de sessão.
  3. Afaste o código de interação do banco de dados. Isso permite que você também forneça melhores informações de erro caso a interação com o banco de dados falhe (não fazer isso oculta pelo menos um erro que pode resultar no comportamento que você descreve como "não está funcionando").
  4. Remova o código desnecessário. Quer dizer, não é necessário. Ter código que não é necessário pode incluir erros que resultam no cenário "não está funcionando" que você tem aqui. Então você está se impedindo de fazer as coisas sem motivo. Um exemplo:ini_set("session.save_handler", "user"); - enquanto você não tem idéia do que você faz, não faça. Não há um manipulador de salvamento predefinido chamado user em PHP, nem você está definindo isso.

E é basicamente isso. Para que eu pudesse identificar dois erros reais causando isso, as outras etapas são necessárias para que você possa lidar com problemas futuros:
  1. Certifique-se de estar sempre relacionado à mesma tabela de banco de dados. Por exemplo, se você escrever na tabela MY_SESSIONS e leia da tabela SESSIONS , isso nunca funcionará.
  2. Certifique-se de que os dados que você devolve ao PHP são compatíveis com os dados esperados. Por exemplo, se você armazenar os dados codificados em Base64 no banco de dados e devolvê-los ao PHP codificado em Base64, não há nada que o PHP possa fazer com esses dados.

Outros problemas potenciais que não são visíveis no seu código:
  1. O esquema de banco de dados que você tem não é adequado para os dados que você armazena nele (você não forneceu o esquema da tabela, então não pode ser dito se isso causa ou não problemas).
  2. O identificador do link do banco de dados pode ser alterado porque o próprio codeigniter está criando uma conexão com o banco de dados. Isso pode levar a possíveis efeitos colaterais. Fornecer explicitamente o identificador de link para a conexão com o banco de dados ajuda a ter um sono tranquilo.
  3. Erros em consultas SQL que passaram despercebidos porque o tratamento de erros para as partes do banco de dados está ausente.

Código de exemplo:
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 refatorado 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.');
        }
    }
}

Código de interação do banco de dados com tratamento de erros:
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);
    }
}