我寫了一個類來將我的會話數據存儲到我的數據庫中(請參見下文)。所有在登錄後第一次加載頁面都可以正常工作,我可以看到數據庫中的數據。然後,print_r($ _ SESSION)返回一個空數組,並更新數據庫條目以將數據列設置爲空,但相應地更新了訪問列。在第二頁上丟失數據庫會話數據
編輯:確認,具有現有會話ID的行正在更新,因爲訪問列具有新的時間值,但數據字段不爲空。
任何幫助非常感謝。謝謝。
<?php
namespace MyCompany\MyProject;
use \PDO;
class Session
{
private $dblayer;
private $user_agent;
public function __construct(PDO $dblayer)
{
$this->dblayer = $dblayer;
$this->user_agent = $_SERVER['HTTP_USER_AGENT'];
session_set_save_handler(
array($this, 'open'),
array($this, 'close'),
array($this, 'read'),
array($this, 'write'),
array($this, 'destroy'),
array($this, 'gc')
);
if ('LIVE' == DEVELOPMENT_MODE) {
session_set_cookie_params(0, '/', '', true, true);
} else {
session_set_cookie_params(0, '/', '', false, true);
}
session_start();
}
public function checkUserAgent()
{
if ($_SERVER['HTTP_USER_AGENT'] === $this->user_agent) {
session_regenerate_id(true);
return true;
}
return false;
}
public function open()
{
if ($this->dblayer) {
return true;
}
return false;
}
public function close()
{
$this->dblayer = null;
if (!$this->dblayer) {
return true;
}
return false;
}
public function read($id)
{
try {
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("SELECT data FROM sessions WHERE id = :id LIMIT 1");
$stmt->execute();
$this->dblayer->commit();
if ($data = $stmt->fetch()) {
return $data['data'];
}
return '';
} catch (\Exception $e) {
$this->dblayer->rollBack();
// will use file_put_contents to save error message, file etc to error log
return false;
}
}
public function write($id, $data)
{
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("REPLACE INTO sessions VALUES(:id, :data, NOW())");
$stmt->bindParam(':data', $data);
$stmt->bindParam(':id', $id);
$stmt->execute();
$this->dblayer->commit();
if ($stmt) {
return true;
}
$this->dblayer->rollBack();
// can i save to error log here?
return false;
}
public function destroy($id)
{
try {
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("DELETE FROM sessions WHERE id = :id");
$stmt->bindParam(':id', $id);
$stmt->execute();
$this->dblayer->commit();
} catch (\PDOException $e) {
$this->dblayer->rollBack();
// again, will save error data to log
echo $e->getMessage();
return false;
}
}
public function gc($max)
{
$to_delete = UNIX_TIMESTAMP(time() - $max);
try {
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("DELETE FROM sessions WHERE access < :to_delete");
$stmt->bindParam(':to_delete', $to_delete);
$this->dblayer->commit();
return true;
} catch (\PDOException $e) {
$this->dblayer->rollBack();
// save error data to log;
return false;
}
}
}
在你的代碼中,你正在使用'rollBack',這可能會導致問題嗎?有東西失敗了,所以它回滾了? – Script47
這是一個很好的觀點,儘管第一次寫得非常好。 – DJC
你的'id'字段是如何確定的,這意味着它在每次擊中都是唯一的? – Script47