PHP сессия истекает через 30 минут: 3 лучших метода + код

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Почему ваша PHP-сессия живёт дольше, чем нужно?

Вы когда-нибудь задумывались, почему после 30 минут бездействия ваш сайт всё ещё помнит, что вы залогинились? Или, наоборот, пользователи жалуются, что их "выкидывает" из системы слишком рано? Проблема управления временем жизни сессии в PHP — одна из самых частых головных болей начинающих (и не только) разработчиков. Вопрос "How do I expire a PHP session after 30 minutes?" собрал тысячи просмотров на Stack Overflow, и это не случайно.

Давайте разберёмся, как заставить PHP-сессию умирать ровно через 30 минут. Мы рассмотрим три подхода: от простого (но коварного) до профессионального. Вы узнаете, почему session.gc_maxlifetime часто не работает так, как вы ожидаете, и как написать надёжный код, который не подведёт.

Проблема: что такое "время жизни сессии" на самом деле?

Прежде чем прыгать в код, давайте разберёмся с матчастью. PHP-сессия — это не просто таймер, который тикает в браузере. Это файл на сервере (обычно в /tmp/), который хранит данные пользователя. "Истечение" сессии означает, что этот файл удаляется или становится недействительным.

Есть три ключевых момента, которые влияют на время жизни:

  • Cookie сессии: браузер хранит идентификатор сессии (обычно в cookie PHPSESSID). У этого cookie есть своё время жизни.
  • Файл сессии на сервере: у него есть время последнего изменения (mtime).
  • Сборщик мусора (GC): PHP периодически чистит старые файлы сессий, но делает это не по расписанию, а случайным образом.

Именно из-за этой "трёхуровневой" архитектуры возникает путаница. Установка только одного параметра часто не даёт нужного эффекта.

Метод 1: Наивный — только session.gc_maxlifetime

Самый очевидный способ, который предлагает документация — установить session.gc_maxlifetime. Кажется, что это и есть ответ на вопрос "How do I expire a PHP session after 30 minutes?". Но не всё так просто.

<?php
// Начало сессии
session_start();

// Устанавливаем время жизни сессии в секундах (30 минут = 1800 секунд)
ini_set('session.gc_maxlifetime', 1800);

// Устанавливаем время жизни cookie сессии тоже на 30 минут
session_set_cookie_params(1800);

// Всё? Нет.
?>

Почему это может не сработать?

  • Сборщик мусора (GC) ленив. Он запускается с вероятностью session.gc_probability / session.gc_divisor (по умолчанию 1/100). То есть, даже если файлу сессии уже час, он может не удалиться при следующем запросе, если GC не сработал.
  • Другие приложения. Если на сервере крутится несколько сайтов, они могут чистить чужие сессии или, наоборот, не чистить ваши.
  • Кэширование. На некоторых хостингах (особенно shared hosting) настройки ini_set могут игнорироваться.

Вердикт: Этот метод — база, но не панацея. Он работает только в идеальных условиях. Для продакшена нужно копать глубже.

Метод 2: Ручной таймер внутри сессии (рекомендуемый)

Этот подход — золотая середина. Вместо того чтобы надеяться на сборщик мусора, мы сами контролируем время последней активности пользователя. Это самый популярный ответ на Stack Overflow по теме сессия php истекает через 30 минут.

Идея проста: при каждом запросе мы проверяем, когда пользователь был активен в последний раз. Если прошло больше 30 минут — уничтожаем сессию.

<?php
session_start();

// Время жизни сессии в секундах
$session_lifetime = 1800; // 30 минут

// Проверяем, установлена ли метка времени последней активности
if (isset($_SESSION['LAST_ACTIVITY'])) {
    // Вычисляем разницу между текущим временем и временем последней активности
    $inactive_time = time() - $_SESSION['LAST_ACTIVITY'];

    // Если прошло больше 30 минут
    if ($inactive_time >= $session_lifetime) {
        // Уничтожаем сессию полностью
        session_unset();     // очищаем переменные сессии
        session_destroy();   // уничтожаем саму сессию

        // Перенаправляем пользователя на страницу логина
        header("Location: login.php?timeout=1");
        exit();
    }
}

// Обновляем метку времени последней активности
$_SESSION['LAST_ACTIVITY'] = time();

// Остальной код страницы...
?>

Почему это круто?

  • Надёжность. Вы не зависите от настроек сервера или сборщика мусора.
  • Прозрачность. Вы точно знаете, когда истечёт сессия.
  • Гибкость. Можно легко менять время жизни для разных типов пользователей (например, админам дать 60 минут, а обычным юзерам — 15).

Важный нюанс: Этот метод не удаляет файл сессии с сервера физически. Он просто делает данные недоступными. Если у вас куча сессий, которые "висят" на сервере, вам всё равно нужен сборщик мусора для очистки мусора. Но для пользователя эффект тот же — его "выкинет" из системы.

Улучшаем метод: добавляем "продление" при активности

Часто нужно, чтобы сессия продлевалась, если пользователь активен. Например, человек читает статью 20 минут, кликает на ссылку — и таймер сбрасывается. Давайте это реализуем:

<?php
session_start();

$session_lifetime = 1800;

if (isset($_SESSION['LAST_ACTIVITY'])) {
    $inactive_time = time() - $_SESSION['LAST_ACTIVITY'];
    if ($inactive_time >= $session_lifetime) {
        session_unset();
        session_destroy();
        header("Location: login.php?timeout=1");
        exit();
    }
}

// Обновляем время последней активности ТОЛЬКО если пользователь что-то делает
// (не при AJAX-опросах, например)
if (!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
    $_SESSION['LAST_ACTIVITY'] = time();
}
?>

Этот код не сбрасывает таймер при AJAX-запросах (например, когда скрипт проверяет новые сообщения каждые 5 секунд). Иначе пользователь мог бы "висеть" в системе вечно.

Метод 3: Хранение сессий в базе данных (промышленный стандарт)

Если вы строите серьёзное приложение (например, интернет-магазин или CRM), хранить се

Блоги

Рекомендаций по книгам