Sessões


1Apresentação

O sistema de sessões permite o armazenamento temporário de variáveis, vinculadas a um visitante. A vantagem é poder realizar processamentos em um controlador com base no processamento realizado anteriormente nos controladores executados antes dele.
Cada sessão é vinculada a um navegador por meio de um cookie definido no primeiro acesso. Isso é transparente, pois é gerenciado pelo framework.

O objeto de gerenciamento de sessão é criado automaticamente pelo Temma, se a configuração assim o previr.


2Configuração

No arquivo etc/temma.php, você pode definir como as sessões são armazenadas (veja a documentação de configuração).

Observe que, se nenhuma fonte for especificada, o Temma usa o mecanismo de sessão nativo do PHP. Note que o PHP armazena os dados de sessão em arquivos, que ficam bloqueados durante o acesso. Isso significa que apenas uma requisição pode acessá-los por vez, o que pode gerar bloqueios se você tiver requisições de longa duração (por exemplo, se você usar controladores de eventos).


3Objeto de sessão

Nos controladores, o objeto de sessão está disponível ao escrever:

$this->_session

Nos demais objetos gerenciados pelo componente de injeção de dependências, o objeto de sessão pode ser acessado ao escrever:

$this->_loader->session

4Leitura de dados

Para ler dados da sessão, basta usar o objeto como um array associativo:

$currentUser = $this->_session['user'];

Para saber se uma variável de sessão existe, ou se ela está vazia:

// a variável está definida?
if (isset($this->_session['myVariable']))
    doSomething();

// a variável está vazia?
if (empty($this->_session['myOtherVariable']))
    doSomethingElse();

// variável não definida: usar um valor padrão
$var = $this->_session['myVariable'] ?? 'defaultValue';

// variável não definida ou vazia: usar um valor padrão
$var = $this->_session['myVariable'] ?: 'defaultValue';

Com o método get(), você pode ler uma variável de sessão, especificando um valor padrão que é retornado caso o dado não esteja presente na sessão:

$var = $this->_session->get('myVariable', 'Default value');

É possível recuperar todas as variáveis de sessão com o método getAll():

$sessVariables = $this->_session->getAll();
$currentUser = $sessVariables['user'];
$basket = $sessVariables['basket'];

Também é possível recuperar todas as variáveis de sessão cujo nome começa com um determinado prefixo, usando o método getPrefix():

$names = $this->_session->getPrefix('name-');

foreach ($names as $nameKey => $nameValue) {
    print($nameKey . ' : ' . $nameValue);
}
/*
 * Por exemplo, isso pode exibir:
 * name-1 : Alice
 * name-2 : Bob
 * name-3 : Camille
 */

print($this->_session['name-1']);
// escreve "Alice"

5Escrita de dados

Para criar ou modificar uma variável de sessão:

$this->_session['myVariable'] = $value;

Se o valor atribuído à variável for null, a variável é removida da sessão.

Para ler e escrever dados, o objeto de gerenciamento de sessão é usado como um array. Mas isso não permite escrever valores diretamente em arrays multidimensionais.
Para modificar um array multidimensional, é preciso primeiro recuperar o array completo, modificá-lo e então sobrescrever a variável de sessão:

// isso não funciona
$this->_session['user']['name'] = 'Einstein';

// é assim que deve ser feito
$user = $this->_session['user'];
$user['name'] = 'Einstein';
$this->_session['user'] = $user;

6Exclusão de dados

Para destruir uma variável de sessão:

unset($this->_session['myVariable']);

Para excluir todas as variáveis da sessão:

$this->_session->clean();

7Extração de dados

A extração de dados consiste em ler as variáveis de sessão e, em seguida, excluí-las da sessão.

É possível extrair dados da sessão, ou seja, lê-los e excluí-los da sessão em uma única chamada ao método extract():

$value = $this->_session->extract('myVariable');

// é equivalente a
$value = $this->_session['myVariable'];
unset($this->_session['myVariable']);

// extract() também pode receber um valor padrão
$value = $this->_session->extract('myVariable', 'default value');

Também é possível extrair todas as variáveis de sessão cujo nome começa com um determinado prefixo. As variáveis recuperadas são excluídas da sessão. Para isso, use o método extractPrefix():

$users = $this->_session->extractPrefix('user-');

foreach ($users as $login => $name) {
    print("$login : $name");
}
/*
 * Por exemplo, isso pode exibir:
 * jrambo : John Rambo
 * jconnor : John Connor
 * jwick : John Wick
 */

8Variáveis flash

8.1Princípio

As variáveis flash são variáveis de sessão com um tempo de vida muito limitado. Na próxima vez que uma página é carregada, elas são extraídas (e, portanto, excluídas) da sessão, e disponibilizadas em variáveis de template.

Para transformar uma variável de sessão em uma variável flash, basta prefixar seu nome com dois sublinhados (__).


8.2Exemplo 1

Vamos imaginar um controlador Article com três ações:

  • view: exibe o conteúdo de um artigo, com base no identificador passado como parâmetro. Se o artigo não existir, a ação redireciona para /article/info, tendo antes criado a variável flash __status com o valor unknown_article.
  • list: exibe a lista de artigos. Se não existir nenhum item, a ação redireciona para /article/info, tendo antes criado a variável flash __status com o valor empty_list.
  • info: exibe uma mensagem de erro, de acordo com o valor da variável flash __status.

Aqui está o arquivo controllers/Article.php:

<?php

/** Controlador de gerenciamento de artigos. */
class Article extends \Temma\Web\Controller {
    /** Ação que exibe um artigo com base em seu identificador. */
    public function view(int $articleId) {
        // recupera o artigo
        $article = ...
        // verifica o artigo
        if (!$article) {
            // cria a variável flash
            $this->_session['__status'] = 'unknown_article';
            // redireciona
            return $this->_redirect('/article/info');
        }
    }
    /** Ação que exibe a lista de artigos. */
    public function list() {
        // recupera os artigos
        $articles = ...
        // verifica os artigos
        if (!$articles) {
            // cria a variável flash
            $this->_session['__status'] = 'empty_list';
            // redireciona
            return $this->_redirect('/article/info');
        }
    }
    /** Ação que exibe as informações. */
    public function info() {
        // nenhum processamento
    }
}
  • Linha 8: recuperação do artigo pelo identificador.
  • Linhas 10 a 15: processamento quando não há artigo com esse identificador.
    • Linha 12: criação da variável flash.
    • Linha 14: redirecionamento.
  • Linha 20: recuperação da lista de artigos.
  • Linhas 22 a 27: processamento quando não há artigos.
    • Linha 24: criação da variável flash.
    • Linha 26: redirecionamento.

Aqui está o arquivo templates/article/info.tpl:

<html>
<body>

    <h1>Informations</h1>
    {* exibe uma mensagem com base na variável flash *}
    {if $__status == 'unknown_article'}
        O artigo solicitado não existe.
    {elseif $__status == 'empty_list'}
        Não há artigos para exibir.
    {else}
        Ocorreu um erro.
    {/if}

</body>
</html>

8.3Exemplo 2

Neste segundo exemplo, vamos evoluir o controlador Article. Quando a ação view encontra um erro (o artigo não existe), ela redireciona para a ação list, para exibir a lista de artigos.

A ação list continua redirecionando para info se não tiver itens para exibir. Por outro lado, se você foi redirecionado a partir da ação view, é o status desta última (unknown_article) que é propagado, e não aquele que indica que não há artigos (empty_list).

Aqui está o arquivo controllers/Article.php:

<?php

/** Controlador de gerenciamento de artigos. */
class Article extends \Temma\Web\Controller {
    /** Ação que exibe um artigo com base em seu identificador. */
    public function view(int $articleId) {
        // recupera o artigo
        $article = ...
        // verifica o artigo
        if (!$article) {
            // cria a variável flash
            $this->_session['__status'] = 'unknown_article';
            // redireciona
            return $this->_redirect('/article/info');
        }
    }
    /** Ação que exibe a lista de artigos. */
    public function list() {
        // recupera os artigos
        $articles = ...
        // verifica os artigos
        if (!$articles) {
            // cria a variável flash
            if ($this['__status'])
                $this->_session['__status'] = $this['__status'];
            else
                $this->_session['__status'] = 'empty_list';
            // redireciona
            return $this->_redirect('/article/info');
        }
    }
    /** Ação que exibe as informações. */
    public function info() {
        // nenhum processamento
    }
}

Linhas 22 a 30: processamento quando não há itens.

  • Linha 24: verifica se a variável de template __status existe e não está vazia. Se for o caso, uma variável flash __status foi definida na página anterior.
  • Linha 25: se a variável de template __status existir e não estiver vazia, usa seu valor para criar uma nova variável flash __status.
  • Linha 27: caso contrário, cria uma variável flash com o valor empty_list.
  • Linha 29: redirecionamento.