Php 在第2页上丢失数据库会话数据
我编写了一个类来将会话数据存储到数据库中(见下文)。登录后的第一个页面加载一切正常,我在数据库中看到了数据 但是,转到下一页,print_r($_SESSION)返回一个空数组,数据库条目已更新为将数据列设置为nothing,但相应地更新了access列 编辑:要确认,将更新具有现有会话ID的行,因为access列具有新的时间值,但数据字段不为空 非常感谢您的帮助。谢谢Php 在第2页上丢失数据库会话数据,php,mysql,session,Php,Mysql,Session,我编写了一个类来将会话数据存储到数据库中(见下文)。登录后的第一个页面加载一切正常,我在数据库中看到了数据 但是,转到下一页,print_r($_SESSION)返回一个空数组,数据库条目已更新为将数据列设置为nothing,但相应地更新了access列 编辑:要确认,将更新具有现有会话ID的行,因为access列具有新的时间值,但数据字段不为空 非常感谢您的帮助。谢谢 <?php namespace MyCompany\MyProject; use \PDO; class Sess
<?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;
}
}
}
在调用第二页时检查会话是否存在,如果不存在,则调用会话\u启动 在第二页上,确保将会话_start(),只需仔细检查,您可能会忽略。虽然大多数类似的情况不太可能有我的确切原因,但该问题确实强调需要了解何时以及如何调用每个会话方法。实际上,问题出在read()方法中,我没有绑定id参数
缺行:
$stmt->bindParam(':id', $id);
因此,任何人有相同的问题,检查所有的方法 在您的代码中,您正在使用回滚
,这可能是导致问题的原因吗?有些东西失败了,所以它正在回滚?这是一个很好的观点,尽管它第一次写得非常好?您的id
字段是如何确定的,这意味着它在每次命中时都是唯一的?查询使用replace_into,id字段是我的主键,因此它插入,除非主键匹配,在这种情况下,它会在插入之前删除该行。access列正在更新。我这样问,可能是因为刷新时找不到ID,因为ID发生了更改,或者是因为数据
字段发生了更改,导致查询失败并回滚,这是可能的吗?另外,这是我第一次遇到REPLACE
子句,所以我不完全确定它是如何工作的。我在下一页实例化了会话类,因此在u构造方法中调用了Session_start()。我在下一页实例化了会话类,因此Session_start()也被调用了在_构造方法中调用