Du använder Codeigniter. Den har funktionen att lagra sessioner i den redan inbyggda databasen.
Ta bara bort din kod som inte fungerar och använd funktionen i Codeigniter istället. Du behöver bara konfigurera den.
Bortsett från det, om du verkligen vill "bo med din", finns det flera problem med din kod. De är lätta att upptäcka om du följer följande punkter:
- Läs om varje återuppringningsfunktion för sessionssparhanteraren. Speciellt vilken data de tar emot och i vilket format (att inte göra det leder till minst ett fel som kan utlösa beteendet som du beskriver som "inte fungerar").
- Gör felloggning. Om du har ett problem med sparahanteraren som leder till att fel uppstår kan de inte ses eftersom utmatning till webbläsaren inte längre är möjlig. Detta kräver att du loggar fel till filen. Detta är mycket viktigt när du felsöker med en sessionssparhanterare.
- Flytta databasens interaktionskod ur vägen. Detta gör att du också kan tillhandahålla bättre felinformation om databasinteraktionen misslyckas (om du inte gör det döljs åtminstone ett fel som kan resultera i beteendet som du beskriver som "inte fungerar").
- Ta bort kod som inte behövs. Jag menar, det behövs inte. Att ha kod som inte behövs kan innehålla fel som leder till att "inte fungerar" scenariot du har här. Så du hindrar dig själv från att få saker gjorda utan anledning. Ett exempel:
ini_set("session.save_handler", "user");
- så länge du inte har en aning om vad du gör, gör det inte. Det finns ingen fördefinierad räddningshanterare som heteruser
i PHP, inte heller definierar du det.
Och det är i princip det. Så jag kunde upptäcka två verkliga fel som orsakar detta, de andra stegen är nödvändiga så att du kan hantera framtida problem:
- Se till att du alltid är relaterad till samma databastabell. Till exempel, om du skriver i tabellen
MY_SESSIONS
och läs från tabellenSESSIONS
, detta kommer aldrig att fungera. - Se till att den data du ger tillbaka till PHP är kompatibel med den data som förväntas. Till exempel, om du lagrar data Base64 kodad i databasen och ger tillbaka den till PHP Base64 kodad, finns det inget PHP kan göra med den data.
Andra potentiella problem som inte är synliga från din kod:
- Databasschemat du har passar inte för den data du lagrar där (du har inte angett tabellschemat så det kan inte sägas om detta orsakar dig problem eller inte).
- Databaslänkens identifierare kan ändras eftersom codeigniter själv skapar en databasanslutning. Detta kan leda till potentiella biverkningar. Att uttryckligen tillhandahålla länkidentifieraren för databasanslutningen hjälper till för en avslappnad sömn.
- Fel i SQL-frågor som blev obemärkta eftersom felhanteringen för databasdelarna saknas.
Exempelkod:
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
klass:
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.');
}
}
}
Databasinteraktionskod med felhantering:
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);
}
}