Introdução: "Por que minha sessão não morre?"
\n\nImagine: você está escrevendo uma loja online, um painel administrativo ou uma área de login. O usuário entrou, trabalhou, foi tomar café — e uma hora depois a sessão ainda está ativa. Os dados no carrinho permanecem, o acesso está aberto. Isso não é apenas inconveniente, mas também perigoso. Especialmente se o site lida com dados de pagamento.
\n\nA pergunta "How do I expire a PHP session after 30 minutes?" é uma das mais populares no Stack Overflow (dezenas de milhares de visualizações). E não é surpresa: desenvolvedores iniciantes frequentemente pensam que basta definir session.gc_maxlifetime — e tudo funcionará. Depois se surpreendem por que a sessão dura horas.
Neste artigo, vamos abordar 4 abordagens reais de como fazer a sessão PHP expirar exatamente em 30 minutos. Você aprenderá por que as configurações padrão podem falhar e qual método escolher para sua tarefa. Vamos lá!
\n\nUm pouco de teoria: como o PHP gerencia o tempo da sessão
\n\nAntes de escrever código, é importante entender dois mecanismos que influenciam a "morte" da sessão:
\n\n- \n
- Tempo de vida do cookie da sessão — quanto tempo o navegador armazena o identificador da sessão (PHPSESSID). Gerenciado pelo parâmetro
session.cookie_lifetime. \n - Tempo de vida dos dados no servidor — quanto tempo o arquivo da sessão fica na pasta /tmp. Gerenciado por
session.gc_maxlifetime. \n
O problema é que o coletor de lixo (GC — garbage collector) é executado probabilisticamente. Por padrão, ele é acionado em 1% das requisições. Isso significa que mesmo se gc_maxlifetime = 1800 (30 minutos), a sessão pode permanecer por mais uma hora até que o GC a alcance.
Portanto, confiar apenas na configuração do servidor é uma má ideia. É necessário verificar o tempo "manualmente".
\n\nMétodo nº 1. Clássico: verificação do tempo na sessão (recomendado)
\n\nEsta é a maneira mais confiável e transparente. Você mesmo armazena na sessão um timestamp da última atividade e, a cada requisição, verifica se já se passaram 30 minutos.
\n\n<?php\nsession_start();\n\n// Define o tempo de vida da sessão — 30 minutos (1800 segundos)\n$timeout_duration = 1800;\n\n// Se houver um timestamp na sessão e ele estiver expirado\nif (isset($_SESSION['LAST_ACTIVITY']) && \n (time() - $_SESSION['LAST_ACTIVITY']) > $timeout_duration) {\n // Destroi a sessão\n session_unset();\n session_destroy();\n // Redireciona para a página de login\n header("Location: login.php?timeout=1");\n exit;\n}\n\n// Atualiza o timestamp (se o usuário estiver ativo)\n$_SESSION['LAST_ACTIVITY'] = time();\n?>\n\nVantagens:
\n- \n
- Controle absoluto: a sessão morrerá exatamente após 30 minutos de inatividade. \n
- Não depende das configurações do PHP e do coletor de lixo. \n
- Fácil de alterar o tempo para diferentes seções do site (ex.: painel admin — 15 minutos, usuário — 60). \n
Desvantagens:
\n- \n
- É necessário adicionar a verificação em cada página (ou colocá-la em um arquivo de inicialização comum). \n
- Se o usuário mantiver a página aberta, mas não clicar — a sessão morrerá. Para alguns cenários (formulário longo), isso é uma desvantagem. \n
Método nº 2. Combinado: gc_maxlifetime + cookie_lifetime
\n\nSe você não quiser escrever uma verificação manual, pode tentar configurar o PHP "pronto para uso". Mas lembre-se das nuances.
\n\n// No início do script, antes de session_start()\n$lifetime = 1800; // 30 minutos\n\n// Define o tempo de vida do cookie da sessão\nsession_set_cookie_params($lifetime);\n\n// Define o tempo máximo de vida dos dados no servidor\nini_set('session.gc_maxlifetime', $lifetime);\n\n// Agora inicia a sessão\nsession_start();\n\nAdicionalmente — para que o GC funcione com mais frequência, você pode reduzir a probabilidade de execução:
\n\nini_set('session.gc_probability', 1);\nini_set('session.gc_divisor', 1); // O GC será executado a cada re