Я знаю, что прошло какое-то время, надеюсь, вы нашли ответ, так как это было опубликовано, но я добавлю свое решение для потомков.
Вызов session_generate_id()
вызовет значение session_id()
изменения:
<?php
$before = session_id();
session_regenerate_id();
$after = session_id();
var_dump($before == $after); // outputs false
Эта проблема проявляется для меня, потому что в обработчике сеанса записи я делал это (без таких фиктивных имен методов, конечно):
<?php
class MySQLHandler
{
function read($id)
{
$row = $this->doSelectSql($id);
if ($row) {
$this->foundSessionDuringRead = true;
}
// snip
}
function write($id, $data)
{
if ($this->foundSessionDuringRead) {
$this->doUpdateSql($id, $data);
}
else {
$this->doInsertSql($id, $data);
}
}
}
метод
записи() работает нормально, если
session_regenerate_id()
никогда не называли. Однако если он был вызван, аргумент $ id для
write()
отличается от $ id, переданного
read()
, поэтому обновление не найдет записи с новым $ id, потому что они никогда не были вставлены.
Некоторые люди предлагают использовать синтаксис «REPLACE INTO» MySQL, но это удаляет и заменяет строку, которая играет веселый хаос, если вы хотите иметь столбец даты создания. То, что я сделал, чтобы решить эту проблему было провести на идентификатор сеанса, который был передан в read
, а затем обновить идентификатор сеанса в базе данных во время записи с помощью идентификатора передается read
как ключ:
<?php
class MySQLHandler
{
function read($id)
{
$row = $this->doSelectSql($id);
if ($row) {
$this->rowSessionId = $id;
}
// snip
}
function write($id, $data)
{
if ($this->rowSessionId) {
$stmt = $this->pdo->prepare("UPDATE session SET session_id=:id, data=:data WHERE session_id=:rowSessionId AND session_name=:sessionName");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':rowSessionId', $this->rowSessionId);
$stmt->bindValue(':data', $data);
$stmt->bindValue(':sessionName', $this->sessionName);
$stmt->execute();
}
else {
$this->doInsertSql($id, $data);
}
}
}