Използвате Codeigniter. Той има функцията да съхранява сесии във вече вградената база данни.
Просто премахнете вашия код, който не работи, и вместо това използвайте функцията на Codeigniter. Трябва само да го конфигурирате.
Освен това, ако наистина искате да "останете със своето", има множество проблеми с вашия код. Лесно се забелязват, ако следвате следните точки:
- Прочетете за всяка функция за обратно извикване за манипулатора за запазване на сесията. Особено кои данни получават и в какъв формат (което не води до поне една грешка, която може да задейства поведението, което описвате като „неработещо“).
- Направете регистриране на грешки. Проблемът с манипулатора на записване, който води до даване на грешки, може да ги остави невидими, защото извеждането в браузъра вече не е възможно. Това изисква да регистрирате грешки във файла. Това е много важно, когато отстранявате неизправности с обработчик на сесия.
- Преместете кода за взаимодействие с базата данни настрани. Това ви позволява също така да предоставите по-добра информация за грешката в случай, че взаимодействието с базата данни е неуспешно (което не скрива поне една грешка, която може да доведе до поведението, което описвате като „не работи“).
- Премахнете кода, който не е необходим. Искам да кажа, че не е необходимо. Наличието на код, който не е необходим, може да включва грешки, които водят до сценария "неработещ", който имате тук. Така че вие си пречите да свършите нещата без причина. Един пример:
ini_set("session.save_handler", "user");
- докато нямате представа какво правите, не го правете. Няма предварително дефиниран обработчик на запис, нареченuser
в PHP, нито вие го дефинирате.
И това е основно всичко. Така че мога да забележа две реални грешки, причиняващи това, другите стъпки са необходими, за да можете да се справите с бъдещи проблеми:
- Уверете се, че винаги сте свързани с една и съща таблица на базата данни. Например, ако пишете в таблица
MY_SESSIONS
и прочетете от таблицаSESSIONS
, това никога няма да работи. - Уверете се, че данните, които връщате на PHP, са съвместими с данните, които очаква. Например, ако съхраните данните Base64, кодирани в базата данни, и ги върнете на PHP Base64 кодирани, PHP не може да направи нищо с тези данни.
Други потенциални проблеми, които не се виждат от вашия код:
- Схемата на базата данни, която имате, не е подходяща за данните, които съхранявате там (не сте предоставили схемата на таблицата, така че не може да се каже дали това ви създава проблеми или не).
- Идентификаторът на връзката към базата данни може да се промени, защото самият codeigniter създава връзка с база данни. Това може да доведе до потенциални странични ефекти. Изричното предоставяне на идентификатора на връзката за връзката към базата данни помага за спокоен сън.
- Грешки в SQL заявки, които са останали незабелязани, защото липсва обработката на грешки за частите на базата данни.
Примерен код:
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
клас:
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.');
}
}
}
Код за взаимодействие с база данни с обработка на грешки:
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);
}
}