Używasz Codeignitera. Ma wbudowaną funkcję przechowywania sesji w bazie danych.
Po prostu usuń kod, który nie działa, i zamiast tego użyj funkcji Codeigniter. Wystarczy to skonfigurować.
Poza tym, jeśli naprawdę chcesz „zostać ze swoim”, istnieje wiele problemy z kodem. Można je łatwo zauważyć, jeśli zastosujesz się do następujących punktów:
- Przeczytaj o każdej funkcji zwrotnej dla obsługi zapisywania sesji. Zwłaszcza jakie dane otrzymują i w jakim formacie (niewykonanie tego prowadzi do co najmniej jednego błędu, który jest w stanie wywołać zachowanie, które określasz jako „niedziałające”).
- Przeprowadź rejestrowanie błędów. Problem z obsługą zapisu, który prowadzi do podawania błędów, może pozostawić je niewidoczne, ponieważ wysyłanie danych do przeglądarki nie jest już możliwe. Wymaga to zapisania błędów do pliku. Jest to bardzo ważne podczas rozwiązywania problemów za pomocą programu obsługi zapisu sesji.
- Odsuń kod interakcji z bazą danych. Pozwala to również na dostarczenie lepszych informacji o błędach w przypadku niepowodzenia interakcji z bazą danych (niewykonanie tego powoduje ukrycie co najmniej jednego błędu, który może spowodować zachowanie, które opisujesz jako „niedziałające”).
- Usuń kod, który nie jest potrzebny. To znaczy, to nie jest potrzebne. Posiadanie kodu, który nie jest potrzebny, może zawierać błędy, które powodują „niedziałający” scenariusz, który masz tutaj. Więc bez powodu przeszkadzasz sobie w wykonywaniu zadań. Jeden przykład:
ini_set("session.save_handler", "user");
- tak długo, jak nie masz pojęcia, co robisz, nie rób tego. Nie ma predefiniowanego programu obsługi zapisu o nazwieuser
w PHP, ani nie definiujesz tego.
I to w zasadzie to. Abym mógł zauważyć dwa prawdziwe błędy, które to powodują, konieczne są inne kroki, abyś mógł poradzić sobie z przyszłymi problemami:
- Upewnij się, że zawsze odnosisz się do tej samej tabeli bazy danych. Na przykład, jeśli napiszesz do tabeli
MY_SESSIONS
i odczytaj z tabeliSESSIONS
, to nigdy nie zadziała. - Upewnij się, że dane, które zwracasz PHP, są zgodne z danymi, których oczekuje. Na przykład, jeśli przechowujesz dane zakodowane w Base64 w bazie danych i oddasz je zakodowane w PHP Base64, PHP nic nie może zrobić z tymi danymi.
Inne potencjalne problemy, które nie są widoczne w Twoim kodzie:
- Schemat bazy danych, który posiadasz, nie pasuje do danych, które tam przechowujesz (nie podałeś schematu tabeli, więc nie można powiedzieć, czy powoduje to problemy).
- Identyfikator łącza do bazy danych może ulec zmianie, ponieważ sam program uruchamiający kod tworzy połączenie z bazą danych. Może to prowadzić do potencjalnych skutków ubocznych. Jawne podanie identyfikatora łącza dla połączenia z bazą danych pomaga w spokojnym śnie.
- Błędy w zapytaniach SQL, które zostały niezauważone, ponieważ brakuje obsługi błędów dla części bazy danych.
Przykładowy kod:
ob_start();
session_name("test");
session_set_cookie_params(0, '/', '.test.com');
$s = new SessionManagement();
$s->register();
session_start();
ECHO $_SESSION['test'], "\n"; # value
Refaktoryzowane SessionManagement
klasa:
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.');
}
}
}
Kod interakcji z bazą danych z obsługą błędów:
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);
}
}