Anda menggunakan Codeigniter. Ini memiliki fitur untuk menyimpan sesi ke dalam basis data yang sudah ada di dalamnya.
Hapus saja kode Anda yang tidak berfungsi dan gunakan fitur Codeigniter sebagai gantinya. Anda hanya perlu mengkonfigurasinya.
Selain itu, jika Anda benar-benar ingin "tetap bersama Anda", ada banyak masalah dengan kode Anda. Mereka mudah dikenali jika Anda mengikuti poin-poin berikut:
- Baca tentang setiap fungsi panggilan balik untuk penangan penyimpanan sesi. Terutama data mana yang mereka terima dan dalam format apa (tidak melakukannya menyebabkan setidaknya satu kesalahan yang dapat memicu perilaku yang Anda gambarkan sebagai "tidak berfungsi").
- Lakukan pencatatan kesalahan. Memiliki masalah dengan save handler yang menyebabkan kesalahan pemberian mungkin membuat mereka tidak terlihat karena output ke browser tidak mungkin lagi. Ini mengharuskan Anda untuk mencatat kesalahan ke file. Ini sangat penting saat Anda memecahkan masalah dengan pengatur sesi.
- Singkirkan kode interaksi database. Hal ini memungkinkan Anda juga untuk memberikan informasi kesalahan yang lebih baik jika interaksi basis data gagal (tidak melakukannya akan menyembunyikan setidaknya satu kesalahan yang dapat mengakibatkan perilaku yang Anda gambarkan sebagai "tidak berfungsi").
- Hapus kode yang tidak diperlukan. Maksudku, itu tidak diperlukan. Memiliki kode yang tidak diperlukan dapat menyertakan kesalahan yang mengakibatkan skenario "tidak berfungsi" yang Anda miliki di sini. Jadi, Anda menghalangi diri Anda untuk menyelesaikan sesuatu tanpa alasan. Salah satu contoh:
ini_set("session.save_handler", "user");
- selama Anda tidak tahu apa yang Anda lakukan, jangan lakukan itu. Tidak ada savehandler standar yang disebutuser
di PHP, Anda juga tidak mendefinisikannya.
Dan itu pada dasarnya. Jadi saya dapat menemukan dua kesalahan nyata yang menyebabkan ini, langkah-langkah lain diperlukan agar Anda dapat mengatasi masalah di masa mendatang:
- Pastikan Anda selalu terkait dengan tabel database yang sama. Misalnya, jika Anda menulis ke dalam tabel
MY_SESSIONS
dan baca dari tabelSESSIONS
, ini tidak akan pernah berhasil. - Pastikan bahwa data yang Anda berikan kembali ke PHP kompatibel dengan data yang diharapkan. Misalnya, jika Anda menyimpan data yang dikodekan Base64 ke dalam database dan mengembalikannya ke PHP yang dikodekan Base64, PHP tidak dapat melakukan apa pun dengan data tersebut.
Potensi masalah lain yang tidak terlihat dari kode Anda:
- Skema database yang Anda miliki tidak sesuai dengan data yang Anda simpan di sana (Anda belum menyediakan skema tabel sehingga tidak dapat dikatakan apakah ini menyebabkan masalah bagi Anda atau tidak).
- Pengidentifikasi tautan basis data mungkin berubah karena codeigniter itu sendiri membuat koneksi basis data. Hal ini dapat menyebabkan potensi efek samping. Memberikan pengenal tautan untuk koneksi database secara eksplisit membantu tidur yang nyenyak.
- Kesalahan dalam kueri SQL yang tidak diketahui karena penanganan kesalahan untuk bagian database tidak ada.
Contoh kode:
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
. yang telah difaktorkan ulang kelas:
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.');
}
}
}
Kode interaksi basis data dengan penanganan kesalahan:
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);
}
}