Du bruger Codeigniter. Den har funktionen til at gemme sessioner i den allerede indbyggede database.
Bare fjern din kode, der ikke virker, og brug funktionen i Codeigniter i stedet for. Du behøver kun at konfigurere det.
Bortset fra det, hvis du virkelig ønsker at "blive hos din", er der flere problemer med din kode. De er nemme at få øje på, hvis du følger følgende punkter:
- Læs om hver tilbagekaldsfunktion for sessionslagringshåndteringen. Især hvilke data de modtager og i hvilket format (ikke at gøre det fører til mindst én fejl, der er i stand til at udløse den adfærd, som du beskriver som "ikke virker").
- Udfør fejllogning. At have et problem med gemmehandleren, der fører til at give fejl, kan efterlade dem usete, fordi output til browseren ikke længere er muligt. Dette kræver, at du logger fejl til filen. Dette er meget vigtigt, når du foretager fejlfinding med en session savehandler.
- Flyt databasens interaktionskode af vejen. Dette giver dig også mulighed for at give bedre fejlinformation, hvis databaseinteraktion mislykkes (hvis du ikke gør det, skjules mindst én fejl, der kan resultere i den adfærd, du beskriver som "ikke virker").
- Fjern kode, der ikke er nødvendig. Jeg mener, det er ikke nødvendigt. At have kode, der ikke er nødvendig, kan inkludere fejl, der resulterer i det "ikke fungerer"-scenarie, du har her. Så du forhindrer dig selv i at få tingene gjort uden grund. Et eksempel:
ini_set("session.save_handler", "user");
- så længe du ikke har nogen anelse om, hvad du laver, så lad være med at gøre det. Der er ingen foruddefineret savehandler kaldetuser
i PHP, og du definerer heller ikke den.
Og det er i bund og grund det. Så jeg kunne se to rigtige fejl, der forårsager dette, de andre trin er nødvendige, så du kan håndtere fremtidige problemer:
- Sørg for, at du altid er relateret til den samme databasetabel. For eksempel, hvis du skriver i tabellen
MY_SESSIONS
og læs fra tabelSESSIONS
, det vil aldrig fungere. - Sørg for, at de data, du giver tilbage til PHP, er kompatible med de data, det forventer. For eksempel, hvis du gemmer data Base64 kodet i databasen og giver det tilbage til PHP Base64 kodet, er der intet, PHP kan gøre med disse data.
Andre potentielle problemer, som ikke er synlige fra din kode:
- Det databaseskema, du har, passer ikke til de data, du gemmer derinde (du har ikke angivet tabelskemaet, så det kan ikke siges, om dette giver dig problemer eller ej).
- Databaselink-id'et kan ændre sig, fordi codeigniter selv opretter en databaseforbindelse. Dette kan føre til potentielle bivirkninger. Eksplicit at angive link-id'et til databaseforbindelsen hjælper til en afslappet søvn.
- Fejl i SQL-forespørgsler, der blev ubemærket, fordi fejlhåndteringen for databasedelene mangler.
Eksempelkode:
ob_start();
session_name("test");
session_set_cookie_params(0, '/', '.test.com');
$s = new SessionManagement();
$s->register();
session_start();
ECHO $_SESSION['test'], "\n"; # value
Refaktoreret SessionManagement
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.');
}
}
}
Databaseinteraktionskode med fejlhåndtering:
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);
}
}