4
respostas

session_set_save_handler() como usar em ambiente docker?

Boa tarde,

Estou tentando implentar a utilização do session_set_save_handler(), porém sem sucesso.

<?php

 // cria-session.php
 
$dbPath = __DIR__ . '/banco.sqlite';
$pdo = new PDO("sqlite:$dbPath");

// $sql = 'CREATE TABLE data_table (id TEXT PRIMARY KEY, data TEXT, access TEXT)';
$sql = 'CREATE INDEX access ON data_table (access)';
$stmt = $pdo->prepare($sql);
$stmt->execute();
<?php

declare(strict_types=1);

namespace Alura\Mvc\Controller;

interface SessionHandlerInterface
{
    public function open(): bool;
    public function close(): bool;
    public function read(string $id): string|false;
    public function write(string $id, string $data): bool;
    public function destroy(string $id): bool;
    public function gc(int $max_lifetime): int|false;
}
<?php
declare(strict_types=1);

namespace Alura\Mvc\Controller;

use PDO;

class MySessionHandler implements SessionHandlerInterface
{
    private PDO $pdo;
    private $dbPath = __DIR__ . '/../../banco.sqlite';
    private string $dataBase = 'data_base';
    
    public function open(): bool
    {
        try {
            $this->pdo = new PDO("sqlite:{$this->dbPath}");
        } catch (\PDOException $th) {
            echo "Error" . $th->getMessage();
            return false;
        }

        return true;
    }

    public function close(): bool
    {
        $this->pdo = null;
        return true;
    }

    
    public function read($id): string | false
    {
        $stmt = $this->pdo->prepare("SELECT data FROM {$this->dataBase} WHERE id = ? ");
        $stmt->bindValue(1, $id);

        if ( $stmt->execute() ) {
            if ($stmt->rowCount() == 0)
                return '';
            return $stmt->fetchColumn();
        }
        return false;
    }

    public function write($id, $data): bool
    {
        $timeStamp = date('YmdHis');
        $stmt = $this->pdo->prepare("REPLACE INTO {$this->dataBase} VALUES(?, ?, ?)");
        $stmt->bindVAlue(1, $id);
        $stmt->bindVAlue(2, $data);
        $stmt->bindVAlue(3, $timeStamp);

        return $stmt->execute();
    }

    public function destroy($id): bool
    {
        $stmt = $this->pdo->prepare("DELETE FROM {$this->dataBase} WHERE id=?");
        $stmt->bindValue(1, $id);
        return $stmt->execute();
    }

    public function gc($maxlifetime): int|false
    {
        $timeStamp = date('YmdHis', time() - $maxlifetime);
        $stmt = $this->pdo->prepare("DELETE FROM {$this->dataBase} WHERE access < ?");
        $stmt->bindParam(1, $timeStamp);
        $stmt->execute();
        if ( $stmt->execute() )
            return $stmt->rowCount();
        return false;
    }
    
}
<?php

// teste.php

require_once __DIR__ . '/vendor/autoload.php';

use Alura\Mvc\Controller\MySessionHandler;

$handler = new MySessionHandler();

session_set_save_handler( $handler, true);

session_start();

$_SESSION['nome'] = 'Edson';

Ao executar o arquivo teste.php, dentro ou fora do container, digo, dentro do ambiente docker e ambiente local, ocorre a seguinte mensagem:

Fatal error: Uncaught TypeError: session_set_save_handler(): Argument #1 ($open) must be of type SessionHandlerInterface, Alura\Mvc\Controller\MySessionHandler given in /var/www/html/teste.php:9
Stack trace:
#0 /var/www/html/teste.php(9): session_set_save_handler(Object(Alura\Mvc\Controller\MySessionHandler), true)
#1 {main}
  thrown in /var/www/html/teste.php on line 9

Não sei o que fazer. Se tiver algum exemplo de algo funcional, agradeço.

4 respostas

Opa Edson, tudo certo?

O erro em questão indica que o primeiro argumento passado para a função session_set_save_handler() deve ser uma instância que implementa a interface SessionHandlerInterface.

Sugiro que verifique se a interface está sendo importada corretamente e no local correto. Deixo abaixo alguns conteúdos sobre o assunto:

Fico à disposição.

Tenha um bom dia e bons estudos.

Opa Gabriel, tudo certo e contigo?

Aparentemente está sim. Estava acompanhando a documentação e também está, aparentemente correto.

O que apareceu pra vc?

Oi!

Não tenho certeza, mas acredito que a interface SessionHandlerInterface é do próprio php e você não deveria ter criado ela no seu projeto. Talvez por isso esteja dando erro de incompatibilidade.

É exatamente o que o Rodrigo falou. Você precisa implementar essa interface e não criar uma própria. :-)