Abrir sessões em PHP de forma econômica

Artigo que mostra alguns cuidados ao se abrir sessão no PHP, de forma que não sobrecarregue o servidor com dados desnecessários.

macaco pensando
Introdução

No artigo Utilizando Sessões em PHP de forma inteligente, foi apresentado o funcionamento das sessões em PHP e algumas estratégias de como fazer bom uso das sessões. Neste artigo, veremos um outro detalhe muito importante, e que não foi citado no primeiro artigo. Trata-se da abertura de sessões de forma econômica, ou seja, apenas quando necessário.

O problema das sessões do PHP

Pergunta: para utilizar sessões em PHP, é necessário chamar session_start?

Resposta: depende.

Se você está em um trecho do script que precisa armazenar algum valor em sessão, então você realmente precisa chamar session_start, para depois guardar algo em $_SESSION. Mas se você está em um trecho do script que precisa apenas ler um valor da sessão, então você não precisa necessariamente chamar session_start, já que você pode, primeiro, verificar se a sessão existe. Afinal, se a sessão não existe, então você já sabe que não vai conseguir ler nada de $_SESSION e, consequentemente, não precisa chamar session_start. Por outro lado, se você consegue identificar que a sessão existe, então você pode chamar session_start para abri-la e tentar ler o que precisava de $_SESSION.

O problema é que, se você não leva isso em consideração, sempre vai chamar session_start (seja para escrita quanto para leitura). Consequentemente, você estará abrindo a sessão em pontos que não precisava e consumindo recursos do servidor desnecessariamente. Se sua sessão está configurada para usar memcache, por exemplo, a cada chamada de session_start você estará alocando um pouco mais de memória. Se está configurada para ser guardada em arquivo, a cada chamada de session_start você estará criando um novo arquivo em disco. Então se seu site recebe milhares de visitas diárias, é importante considerar um uso econômico das sessões.

Porém, o PHP não oferece nenhum recurso nativo para checar se a sessão "existe". Então este artigo vai discutir uma estratégia de como controlar isso por sua conta.

Como saber que a sessão existe

Em um mesmo script, existem pontos em que a sessão existe e pontos em que ela não existe mais. Por exemplo:

<?php
// Neste ponto a sessao ainda nao existe

session_start(); // Criando a sessao

// Neste ponto a sessao existe e pode ser manipulada

session_destroy(); // Destruindo a sessao

// Neste ponto a sessao nao existe mais
?>

Ou seja, para determinar se ela existe, devemos considerar as funções que o script chamou. Além disso, devemos considerar, inicialmente, se o usuário informou um ID de sessão (SESSIONID) quando acessou o script. Se o usuário informou o SESSIONID (via cookie ou trans_sid), então ele provavelmente possui a sessão, mesmo que ela ainda não tenha sido aberta.

Para saber se o usuário informou um SESSIONID, você pode verificar se existe o cookie com o nome do cookie de sessão:

$existe = isset($_COOKIE[session_name()]);

Se você usa trans_sid para trafegar o ID de sessão (não é recomendado):

$existe = isset($_GET[session_name()]);

Estratégias para controlar a abertura de sessões em PHP

Com o que vimos, podemos listar algumas estratégias importantes para se abrir sessões de forma econômica:

  • Encapsular em uma classe as funções session_start e session_destroy, para conseguirmos saber, em qualquer ponto do código, se a sessão existe ou não e se ela está aberta ou não.
  • Encapsular a função session_write_close, para conseguirmos saber, em qualquer ponto do código, se a sessão foi fechada.
  • Utilizar o padrão singleton para que exista apenas uma instância da classe e, consequentemente, quando um ponto do código abrir a sessão, outro ponto do código tenha condições de saber que isso ocorreu.
  • Verificar, inicialmente, se o usuário informou um SESSIONID.
  • Utilizar um atributo para controlar se a sessão existe o não.
  • Utilizar um atributo para controlar se a sessão está aberta ou não.

Note que a sessão pode existir, mas ainda não estar aberta para uso. Portanto, é importante controlar se a sessão está aberta para uso ou não. No PHP 5.4, podemos verificar isso chamando a função session_status (checando se ela retorna PHP_SESSION_ACTIVE). Quando chamamos a função session_write_close, a sessão continua existindo, mas não está mais aberta.

Com estas ideias em mente, você tem condições de bolar como será feito o acesso à sessão de forma econômica. Uma ideia é implementar dois métodos: abrirParaLeitura e abrirParaEscrita, então usar de acordo com a necessidade. O primeiro só abriria a sessão se ela existe, a segunda abriria incondicionalmente.

Uma outra ideia é criar um método get e outro set, sendo que eles próprios controlariam a abertura da sessão, conforme a necessidade. Esta ideia eu implementei e submeti ao site PHPClasses. Em breve, estará disponível no link: Smart Session.

9 comentários

Unknown disse...

Parabéns pelo post!
Seria interessante se você entrasse em mais detalhes e colocasse exemplos práticos das sugestões e estratégias.

Rubens Takiguti Ribeiro (autor do blog) disse...

Olá, Frederico

Na verdade fiz uma implementação desta ideia e coloquei no site phpclasses.org. Só falta a aprovação pelo autor, então ficará disponível no link do final do artigo.

Premiere disse...

Sempre utilizei sem fazer a abertura com session_start.

Utilizo uma função criada por mim:

public function session($name, $value = null) {
if(!is_null($value)) {
$_SESSION[$name] = $value;
} else {
if(isset($_SESSION[$name])) {
return $_SESSION[$name];
} else {
return null;
}
}
}

Anônimo disse...

Tipo eu tive um problema com PHP 5.5.12 devido ao fato de não poder utilizar variáveis vazias ou não existente, ou seja dava erro ate para testar, ai descobri um método que funciona em qualquer caso nãos ei se é o melhor mais estarei compartilhando.
$_SESSION = array();
if (count($_SESSION)==0) {
session_start();
}


//Admitindo que não utilizaria session_start vazio, ou seja se ele esta vazio ele não existe
depois disso para verificar se contem uma certa chave
//Obs: declarar que $_SESSION = array, não paga os dados do $_SESSION caso já possua algum valor, pelo menos no meu caso não apagou.

$contem_chave= 0; //por padrão não contem a chave
$key=""; //evita erros caso não exista nenhum atributo no $_SESSION
$value=""; //evita erros caso não exista nenhum atributo no $_SESSION
if(count($_SESSION)>0){ //como disse antes se session esta vazio ele não existe
foreach($_SESSION as $key => $value){ //Carrega as variáveis do session
if($key == "id"){ //verifica se já existe um $_SESSION['id']
$contem_chave= 1; //se existir indica que contem
}
}
}
//o resto e simples tambem pode ser usado como boleano ou inserido a função dentro do if.
Bem a ideia e que isso evita qualquer erro com relação a chamada

Anônimo disse...

Boa tarde Rubens, preciso de uma ajuda sua...por favor.

Fiz um sistema de login para acesso a um website, porém o mesmo código se perde em alguns recursos quando este está online (server centralserver). Por exemplo. Ao deslogar e voltando no icone pelo navegador, a sessão continua ligada. Esse mesmo código funciona certinho como local (xamp)...ou seja, quando desloga e volto ja pede pra logar automaticamente.

O que preciso alterar para que funcione no server da central server? (obs. eles - central server não ajudam no código)


Abaixo o arquivo logout.php.

---------------------------------------------------------------
session_start();

unset($_SESSION["login_usuario"]);
unset($_SESSION["senha_usuario"]);
session_destroy();

----------------------------------------------------------------

Obrigado!
Alessandro

Rubens Takiguti Ribeiro (autor do blog) disse...

Oi, Alessandro

Aparentemente seu código para destruir a sessão está correto. O que você também pode fazer é forçar a limpeza do cookie de sessão assim:
setcookie(session_name(), '', $_SERVER['REQUEST_TIME'] - 1000);

Além disso, precisa se certificar de que nenhum conteúdo foi impesso na tela no momento em que o session_start foi chamado. Dê uma lida neste outro artigo também:
http://rubsphp.blogspot.com.br/2011/04/sessoes-em-php.html

Unknown disse...

Ao armazenar $_SESSION['a']=25; em meu site.... essa variavel podera ser acessada em um outro PC que acessa a mesma página?

Rubens Takiguti Ribeiro (autor do blog) disse...

Oi, Alessandro

Por padrão, os dados de sessão são armazenados em arquivos no servidor (onde estão os códigos PHP). É possível configurar para que sejam armazenados em outros meios, como bancos de dados ou memcache (neste caso, podem ficar no mesmo servidor ou em servidores diferentes).

Mas não faz sentido serem acessados pelo PC que acessou a página. O PC consegue apenas acessar uma página e esta página (que está no servidor) tem acesso aos dados da sessão e pode exibí-los ou não.

Sugiro que leia este outro artigo, que explica o funcionamento das sessões em detalhes:
http://rubsphp.blogspot.com.br/2011/04/sessoes-em-php.html