Avatar ·

Как проверить, запущена ли уже сессия PHP, и избежать ошибки «headers already sent»

Привет всем! Я новичок в PHP и пишу небольшой сайт с авторизацией. У меня есть несколько скриптов, которые работают с сессиями. В одном файле я запускаю сессию с помощью session_start(), а затем подключаю другие файлы через include. Проблема в том, что если я случайно дважды вызываю session_start() в разных файлах, PHP выдаёт ошибку: Warning: session_start(): Cannot send session cookie - headers already sent Я понимаю, что эта ошибка возникает, потому что заголовки уже были отправлены, и повторный вызов session_start() невозможен. Но как мне проверить, запущена ли уже сессия, чтобы не вызывать session_start() повторно? Я пробовал использовать @ в начале, чтобы подавить ошибку, но это плохая практика, как я понял. Вот пример моего кода: // config.php session_start(); $_SESSION['user'] = 'admin'; // page.php include 'config.php'; session_start(); // Здесь выдаёт ошибку, если config.php уже вызвал session_start() Мне нужно что-то вроде: if (session_not_started()) { session_start(); } Подскажите, как правильно это сделать? Заранее спасибо! <<>>

Проверка состояния сессии с помощью session_status()

Начиная с PHP 5.4.0 существует встроенная функция session_status(), которая возвращает текущее состояние сессии. Это наиболее правильный и современный способ проверить, запущена ли уже сессия.

Функция возвращает одну из трёх констант:

  • PHP_SESSION_DISABLED — сессии полностью отключены в конфигурации PHP.
  • PHP_SESSION_NONE — сессии включены, но ни одна сессия ещё не запущена.
  • PHP_SESSION_ACTIVE — сессия уже активна.

Таким образом, вы можете безопасно вызывать session_start() только если сессия ещё не запущена:

<?php
if (session_status() === PHP_SESSION_NONE) {
    session_start();
}
?>

Этот код проверяет, что сессии включены и не активны, и только тогда запускает новую сессию. Если сессия уже запущена, ничего не происходит — никаких ошибок.

Полный пример с include

В вашем случае лучше всего обернуть вызов session_start() в проверку в каждом файле, который может быть подключён. Так вы избежите дублирования:

<?php
// session_helper.php
function ensure_session_started() {
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
}
?>

// config.php
require_once 'session_helper.php';
ensure_session_started();
$_SESSION['user'] = 'admin';

// page.php
require_once 'session_helper.php';
require_once 'config.php'; // config.php тоже вызывает ensure_session_started()
ensure_session_started(); // Второй вызов безопасен — сессия уже активна
?>

Старый способ (до PHP 5.4)

Если вы работаете с устаревшей версией PHP (что не рекомендуется), можно проверять через session_id():

<?php
if (session_id() === '') {
    session_start();
}
?>

session_id() возвращает пустую строку, если сессия ещё не начата. Однако этот метод менее надёжен, так как session_id() может вернуть пустую строку и в случае, если сессии отключены. Поэтому предпочтительнее использовать session_status().

Важные замечания

  • Всегда вызывайте session_start() до любого вывода в браузер (включая пробелы, HTML-теги, echo). Иначе получите ошибку "headers already sent".
  • Используйте require_once вместо include или require для конфигурационных файлов с сессиями — это гарантирует, что файл будет подключён только один раз.
  • Рассмотрите использование единой точки входа (например, index.php), где сессия запускается один раз, а все остальные скрипты подключаются уже после.

Таким образом, лучший ответ на ваш вопрос — использовать session_status() === PHP_SESSION_NONE для безопасного и читаемого кода.

<<>>

Альтернативный подход: единая точка входа

Вместо того чтобы проверять статус сессии в каждом файле, можно организовать архитектуру приложения так, чтобы session_start() вызывался только один раз — в самом начале выполнения скрипта. Это избавляет от необходимости повторных проверок.

Создайте файл bootstrap.php (или init.php), который подключается самым первым:

<?php
// bootstrap.php
session_start();
?>

Затем в каждом скрипте, который должен работать с сессией, подключайте этот файл только один раз через require_once:

<?php
// index.php
require_once 'bootstrap.php';
// Дальше можно подключать любые другие файлы
// session_start() уже вызван, ошибок не будет
?>

Этот подход особенно удобен для небольших проектов и при использовании MVC-фреймворков, где есть чёткая точка входа (например, public/index.php).

Если же вы всё-таки предпочитаете проверять статус, используйте session_status() — это стандартное и надёжное решение для современных версий PHP.