我编写了一个类来将会话数据存储到我的数据库中(见下文)。登录后,一切正常,第一页加载,我看到数据库中的数据。
但是,继续下一页,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;
}
}
}
答案 0 :(得分:0)
在调用第二页时检查Session是否存在,如果不是,则调用session_start。
答案 1 :(得分:0)
在第二页上,确保放置session_start(); ,只需仔细检查,你可能会忽略。
答案 2 :(得分:0)
虽然大多数类似案例不太可能具有我所做的确切原因,但问题确实强调需要了解何时以及如何调用每个会话方法。问题实际上是在read()方法中,我没有绑定id参数。
缺少一行:
$stmt->bindParam(':id', $id);
所以任何人都有同样的问题,请检查所有方法!