Календарь
Расписание
май 2024
 -  - 1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31  -  -

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

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

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

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

  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
  function sum($a, $b){
    return $a + $b;
  }
?> 

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

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

Резюме:

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

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

15.02.2015

Понравился материал? Поделись с друзьями!