Опасная ошибка: headers already sent

Опасная ошибка: headers already sent

Здравствуйте, друзья!

Сегодня я хочу рассказать вам об одной очень популярной и загадочной ошибке. Наверняка, многие из вас во время отладки своих программ сталкивались со следующим сообщением: headers already sent. Переводится на русский язык данная запись как заголовки уже отправлены.

Чтобы понять суть этой ошибки давайте вспомним структуру hhtp-пакетов:

  1. Стартовая строка — определяет тип сообщения;
  2. Заголовки — характеризуют тело сообщения, параметры передачи и прочие сведения;
  3. Тело сообщения — непосредственно данные сообщения.

Т.е. говоря headers already sent программа ругает нас, за то, что мы уже где-то начали формировать тело сообщения (3-ю часть http-пакета), но снова хотим отправить заголовки (2-ую часть).

Приведу пару примеров: лёгкий и адский с точки зрения возможности заметить ошибку.

Пример 1 – лёгкий.

//Получаем что-то из массива $_GET
$id = $_GET[‘id’];
//Делаем отладочный вывод
echo $id;
// Стартуем сессию
session_start();
//И дальше много php и html, работающего правильно.

Будет выведена ошибка:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent

Мы не имели права вызывать функцию session_start(), после использования оператора echo. Такую ошибку исправить несложно – уберите отладочное echo.

Пример 2 – жуткий.

Представим, что у нас есть абстрактный файл модели model.php, который мы подключаем на нужную нам страничку a.php.

//Подключаем какой-то модуль
include_once('model.php');
// Стартуем сессию
session_start();
//И дальше много php и html, работающего правильно.

Но неожиданно денвер снова говорит:

Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent

Как? Почему? Ведь мы ещё не начинали формирования тела сообщения! И вот здесь прежде чем удастся найти ошибку можно расколотить компьютер или удалить денвер. А всё приключилось потому, что мы нарушили золотое правило – никогда не закрывайте блок php, если в конкретном файле после него не идёт html.

Давайте ещё раз взглянем на файл модели:

И оказывается, что мы всего-то на всего случайно поставили пробел после закрывающего ?>… Ненаходимая ошибка, этот пробел невозможно было и представить себе. Как же с этим бороться? А очень просто – не пишите закрывающее ?> в файлах с чистым php-кодом, и всё будет в порядке.

Так же важно понимать, что речь идёт не только о конкретной функции session_start, но и о всех остальных, которые выполняют отправку заголовков, например: setcookie, header итд.

Резюме:

  1. Не забывайте о том, что нельзя отправлять заголовки после того, как началось формирование тела сообщения
  2. Не пишите закрывающее ?> в файлах с чистым php

И об ошибке headers already sent Вы забудете!