Vlastní session handler pro db
- jannabel
- Člen | 2
Zdravím, mám dotaz ohledně nastavení vlastního session handleru, respektive potřebuju pochopit chování nette kolem sessions. Bohužel toho o tom v dokumentaci moc není (nebo nevím, kde hledat). Mám už prolezlé fórum skrz naskrz a nezdá se, že by tu byla odpověď na můj problém.
Konkrétně mi to háže chybu
Nette\InvalidStateException Failed to read session data: user (path: )
Podle Tracy to vypadá, že to do databáze přistupuje v pořádku. V DB mám pole nastavené na longtext (někdo už tu na fóru řešil podobný problém a tam to bylo právě délkou dat, ale to u mě asi není ten problém). Když si dumpnu výsledek dotazu v metodě read(), vyhodí mi to toto
/srv/app/app/System/SessionHandler.php:50: NULL
1 869.3 ms
1.8 ms / 3
×
ErrorException: session_write_close(): Cannot call session save handler in a recursive manner in Unknown:0 Stack trace: #0 /srv/app/vendor/nette/utils/src/Utils/Callback.php(77): Tracy\Debugger::errorHandler(2, 'session_write_c...', 'Unknown', 0, NULL) #1 [internal function]: Nette\Utils\Callback::Nette\Utils\{closure}(2, 'session_write_c...', 'Unknown', 0, NULL) #2 [internal function]: session_write_close() #3 {main} (stored in /srv/app/app/../log/exception--2020-09-23--14-18--086ac148f1.html)
common.neon
services:
sessionHandler: App\System\SessionHandler
session:
handler: @sessionHandler
SessionHandler
namespace App\System;
use Nette;
final class SessionHandler implements \SessionHandlerInterface
{
/** @var Nette\Database\Context */
private $database;
public $maxlifetime;
public function __construct(\Nette\Database\Context $database)
{
$this->database = $database;
$this->maxlifetime = 43200;
}
public function open($savePath, $sessionName)
{
$this->lockName = 'session_' . session_id();
if ($this->database->query("SELECT IS_FREE_LOCK(?) AS lo", $this->lockName)->fetch()->lo) {
$this->database->query("SELECT GET_LOCK(?, ?)", $this->lockName, 1000);
return true;
} else {
return false;
}
}
public function close()
{
$this->database->query("SELECT RELEASE_LOCK(?)", $this->lockName);
return true;
}
public function read($id)
{
$row = $this->database->fetchField("SELECT session_data FROM session_data WHERE session_id=? AND session_expires > '" . date('Y-m-d H:i:s') . "'", [$id]);
if ($row) {
return $row;
} else {
return false;
}
}
public function write($id, $data)
{
$DateTime = date('Y-m-d H:i:s');
$NewDateTime = date('Y-m-d H:i:s', strtotime($DateTime . ' + 12 hour'));
$query = $this->database->query("REPLACE INTO session_data SET ?", ['session_id' => $id, 'session_expires' => $NewDateTime, 'session_data' => $data]);
if ($query) {
return true;
} else {
return false;
}
}
public function destroy($id)
{
$query = $this->database->query("DELETE FROM session_data WHERE session_id =?", [$id]);
if ($query) {
return true;
} else {
return false;
}
}
public function gc($maxlifetime)
{
$query = $this->database->query("DELETE FROM session_data WHERE ((UNIX_TIMESTAMP(session_expires) + ?) < ?)", [$maxlifetime, $maxlifetime]);
if ($query) {
return true;
} else {
return false;
}
}
}
Děkuji za pomoc