Опасная ошибка: headers already sent
Здравствуйте, друзья!
Сегодня я хочу рассказать вам об одной очень популярной и загадочной ошибке. Наверняка, многие из вас во время отладки своих программ сталкивались со следующим сообщением: headers already sent. Переводится на русский язык данная запись как "заголовки уже отправлены".
Чтобы понять суть этой ошибки, давайте вспомним структуру http-пакетов:
- Стартовая строка — определяет тип сообщения;
- Заголовки — характеризуют тело сообщения, параметры передачи и прочие сведения;
- Тело сообщения — непосредственно данные сообщения.
Т.е. говоря 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
function sum($a, $b){
return $a + $b;
}
?>
И оказывается, что мы всего-то навсего случайно поставили пробел после закрывающего ?>… Ненаходимая ошибка, этот пробел невозможно было и представить себе. Как же с этим бороться? А очень просто – не пишите закрывающее ?> в файлах с чистым php-кодом, и всё будет в порядке.
Также важно понимать, что речь идёт не только о конкретной функции session_start, но и обо всех остальных, которые выполняют отправку заголовков, например: setcookie, header итд.
Резюме:
- Не забывайте о том, что нельзя отправлять заголовки после того, как началось формирование тела сообщения
- Не пишите закрывающее ?> в файлах с чистым php
И об ошибке headers already sent Вы забудете!
15.02.2015
Понравился материал? Поделись с друзьями!