С этой ошибкой ко мне постоянно обращаются и спрашивают: " Где ошибка? ". Подобных писем за всё время я получил где-то штук 500 , не меньше. Пора с ошибкой " Cannot modify header information - headers already sent " уже заканчивать. В этом материале я расскажу о причинах возникновения данной ошибки, а также о том, к...
С этой ошибкой ко мне постоянно обращаются и спрашивают: "Где ошибка?". Подобных писем за всё время я получил где-то штук 500, не меньше. Пора с ошибкой "Cannot modify header information - headers already sent" уже заканчивать. В этом материале я расскажу о причинах возникновения данной ошибки, а также о том, как её решить.
Если перевести данную ошибку на русский язык, то получится примерно следующее: "Нельзя изменить заголовок, поскольку они уже отправлены". Что это за "заголовки"? Давайте разберёмся.
Когда сервер возвращает ответ клиенту, помимо тела (например, HTML-кода страницы), идут ещё и заголовки. В них содержится код ответа сервера, cookie, кодировка и множество других служебных параметров. Может ли PHP-скрипт отправить заголовок? Конечно, может. Для этого существует функция header().
Данная функция, например, постоянно используется при редиректе. Также данная функция регулярно используется при генерации изображении в PHP.
Также заголовки модифицируются при отправке cookie и при начале сессии (функция session_start()).
А теперь о том, почему же всё-таки возникает ошибка? Сервер всегда сначала отдаёт серверу заголовки, а потом тело. Если сервер уже вернул заголовки, потом пошло тело, и тут он встречает какой-нибудь session_start(). Оказывается горе-программист забыл отправить заголовки до начала тела, и теперь хочет догнать уже ушедший поезд.
Вот код с ошибкой "Cannot modify header information - headers already sent":
<html>
<?php
session_start(); // А давайте начнём сессию
?>
Разумеется, такой бред PHP не прощает. И надо было писать так:
<?php
session_start(); // А давайте начнём сессию
?>
<html>
Вот этот скрипт уже не вызовет никаких ошибок, потому что сначала отправляются все заголовки, а уже потом идёт генерация тела ответа сервера.
Другой пример кода с ошибкой:
<?php
echo "Hello!"; // Что-нибудь выведем
session_start(); // А давайте начнём сессию
?>
То же самое, почему-то сначала выводится тело (либо его кусок), а потом вспомнили, что ещё и надо заголовки модифицировать.
Как будет правильно переписать данный код, подумайте сами.
Ещё пример:
<?php
$error = true; // Были ли ошибки?
if ($error) echo "Произошла ошибка";
header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>
Когда у автора такого кода, ничего не получается, он удивляется от этой ошибки и говорит: "Очень странное совпадение, когда операция проходит успешно, всё хорошо, а когда какая-то ошибка, мне сообщают Cannot modify header information - headers already sent". Не дословно, но смысл именно в этом.
Проблема та же самая, и правильно писать так:
<?php
$error = true; // Были ли ошибки?
if ($error) echo "Произошла ошибка";
else header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>
Есть и труднозаметные ошибки:
<?php
header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>
Ошибка в данном коде возникает из-за пробела, который присутствует перед <?php. Пробел - это обычный символ, и он является частью тела ответа. И когда сервер его видит, он делает вывод о том, что заголовков больше не будет и пора выводить тело.
Бывают и следующие ошибки, имеющие всё ту же природу. Допустим есть файл a.html:
<?php echo "Hello"; ?>
Далее есть другой файл с таким кодом:
<?php
require_once "a.html";
header("Location: ".$_SERVER["HTTP_REFERER"]); // Делаем редирект обратно
exit;
?>
И человек искренне удивляется, откуда ошибка, если он ничего не выводил? Поэтому смотреть надо не конкретно 1 файл, а все файлы, которые подключаются в нём. И в тех, что подключаются у подключаемых, тоже надо смотреть, чтобы не было вывода.
И последний момент, но уже более сложный. Оказывается, что иногда эта ошибка происходит и при правильном коде. Тогда всё дело в кодировке. Убедитесь, что кодировка файла "UTF-8 без BOM", причём именно "без BOM", а не просто "UTF-8". Поскольку BOM - это байты, идущие в самом начале файла, и они являются выводом.
Очень надеюсь, что этот материал поможет решить абсолютно все проблемы, связанные с ошибкой "Cannot modify header information - headers already sent", поскольку я постарался осветить все возникающие проблемы. А дальше надо включить голову, и подумать, а что в Вашем коде не так?
