Vlastní session handler pro db

jannabel
Člen | 2
+
0
-

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

stpnkcrk
Generous Backer | 190
+
0
-

Muzes se inspirovat u reseni ktere ma na GitHubu Michal Spacek.

https://github.com/…sion-handler

jannabel
Člen | 2
+
0
-

Funguje. Paráda díky moc! :)