Сессии в PHP: Почему иногда метод empty($_SESSION[‘token’]) возвращает true, даже если пользователь только что авторизовался?
Проблема, когда `empty($_SESSION[‘token’])` возвращает `true` сразу после авторизации пользователя — одна из самых распространённых и неочевидных в PHP-разработке. Рассмотрим основные причины и способы их устранения.
**1. Забытый вызов session_start()**
Самая частая причина — отсутствие `session_start()` в начале скрипта, который читает сессию. Даже если вы записали `$_SESSION[‘token’]` на странице авторизации, на следующей странице сессия не будет доступна без явного вызова `session_start()`. Убедитесь, что этот вызов стоит до любого вывода HTML и до обращения к `$_SESSION`.
**2. Разные настройки session.cookie_domain или session.cookie_path**
Если приложение работает на нескольких поддоменах или в разных директориях, PHP может создавать разные сессии для разных путей. Проверьте `php.ini` или вызов `session_set_cookie_params()` — параметры должны совпадать на всех страницах.
**3. Перезапись $_SESSION после записи токена**
Иногда разработчики случайно делают `$_SESSION = []` или `session_unset()` после записи токена — например, в middleware или в базовом контроллере. Проверьте весь стек вызовов после авторизации.
**4. Конфликт session_regenerate_id()**
Если вы вызываете `session_regenerate_id(true)` (с удалением старой сессии) до того, как данные были записаны, новая сессия окажется пустой. Убедитесь, что `session_regenerate_id()` вызывается уже после записи данных в `$_SESSION`.
**5. Проблемы с хранилищем сессий**
Если сессии хранятся в файлах, убедитесь, что директория `session.save_path` доступна для записи. При использовании Redis или Memcached — что соединение установлено корректно и ключ не истёк раньше времени.
**6. Гонка запросов (Race Condition)**
При AJAX-запросах возможна ситуация, когда второй запрос читает сессию раньше, чем первый успел её записать. PHP блокирует файл сессии на время выполнения скрипта, поэтому параллельные запросы могут читать устаревшие данные.
**7. Значение токена — пустая строка или null**
Функция `empty()` возвращает `true` не только для несуществующих ключей, но и для значений `»`, `null`, `0`, `false`, `[]`. Если токен был записан как пустая строка или `null`, `empty()` вернёт `true`. Используйте `isset($_SESSION[‘token’])` для проверки существования ключа, а `empty()` — только когда нужно проверить и существование, и непустоту.
**Рекомендации по диагностике:**
— Добавьте `var_dump($_SESSION)` сразу после `session_start()` для отладки.
— Проверьте `session_id()` на обеих страницах — идентификаторы должны совпадать.
— Используйте `isset()` вместо `empty()` там, где важно только наличие ключа.
— Логируйте момент записи и чтения токена с временными метками.
