Что означает предупреждение «headers already sent»
Давайте разберёмся, что происходит, когда мы заходим на сайт. Например, когда мы в браузере открываем страницу http://www.example.ru/file.php, то браузер запрашивает у DNS сервера, какой IP адрес принадлежит серверу www.example.ru. После этого он подключается по протоколу TCP к этому IP адресу на порт 80 (этот порт используется по умолчанию для HTTP) и отправляет текстовый запрос наподобие такого:
GET /file.php HTTP/1.1 Host: www.example.ru User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: ru,chrome://global/locale/intl.properties;q=0.5 Accept-Encoding: gzip, deflate Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Cookie: user=2; var=blablabla
Этим запросом в первой строке браузер указывает, что хочет просто получить страницу (GET), указывает адрес страницы и версию протокола (сейчас используются только две версии — 1.0 и 1.1. версия 0.9 устарела и сейчас не используется).
Так же обязательным является параметр Host. Т.к. на каждом сервере может быть несколько разных сайтов, то мы должны указать, к какому именно сайту мы хотим обратиться.
Остальные параметры необязательны. ими браузер просто рассказывает о себе (User-Agent) и рассказывает серверу, как он хочет общаться. Но сейчас речь не об этом.
В ответ на этот запрос веб-сервер запускает выполнение нашего php-скрипта, к которому обращается браузер. И веб-сервер отправляет браузеру результат работы скрипта. но перед этим он отправит свои заголовки ответа.
HTTP/1.1 200 OK Date: Tue, 09 Aug 2011 06:59:22 GMT Server: Apache X-Powered-By: PHP/5.3.5 Content-Length: 1234 Content-Type: text/html; charset=windows-1251 Set-Cookie: PHPSESSID=3ms50sjl2pt2s19sns5udiryn6; path=/ .
Как вы видите, заголовки идут вначале, а после одной пустой строки начинается тело самого html, который мы генерируем с помощью php-скрипта.
И вот мы подошли к основной сути. когда PHP приказывает веб-серверу начать отправлять само содержимое брузеру, то веб-серверу не остаётся ничего, кроме как отправить вначале все заголовки, которые имеются у него на текущий момент. Поэтому после этого PHP уже не сможет изменить эти заголовки.
Функция header() изменяет любой заголовок. Функция setcookie() добавляет куки к заголовку Set-Cookie, поэтому тоже не может работать после отправки заголовков. session_start() добавляет куки с идентификатором сессии (как в примере выше).
А пока найдём пути решения этой проблемы. Чаще всего такие ситуации происходят из-за использования BOM. BOM — это 2 или 3 невидимых символа в начале файла. Эти символы указывают на то, какая используется кодировка. Многие текстовые редакторы по умолчанию добавляют BOM ко всем файлам юникодовской кодировкой (например UTF-8). Например, создадим в блокноте файл
И сохраним его в кодировке UTF-8. Но если мы теперь просмотрим файл в кодировке cp1251, то увидим, что вначале файла добавлены символы:
Именно эти символы и создают проблему. Ведь PHP исполняет свой код только внутри тегов . всё что снаружи отправляется браузеру как есть. Получается, что эти 3 байта сразу же отправятся к браузеру ещё до начала интерпретации PHP-кода. Хотя, по умолчанию в php.ini включен output_buffering и установлен в значение 4096. поэтому проблемы с BOM не должно быть. однако, у многих пользователей она почему-то есть. Подозреваю, что это следствие использования разных кривых сборок.
?php>
Я вижу 2 пути решения это проблемы:
1. Включить в php.ini
На вашем компьютере это должно помочь. Но если вы позже закачаете свой сайт на хостинг, то у вас не будет уверенности, что там включен этот буфер.
2. Запретить текстовому редактору сохранять BOM. Но тут уже всё зависит от возможностей текстового редактора, который вы используете. Например, я пользуюсь Notepad++. там можно открыть меню «Кодировки» и выбрать «Преобразовать в UTF-8 без BOM».
Если вы уверены, что BOM не используется, значит где-то перед функциями header(), setcookie() и т.п. вы сами отправляете данные пользователю. Возможно, перед открытием тега Если вначале вам необходимо отправлять данные, то можно включить использование буфера, что бы данные не отправлялись сразу браузеру:
ob_start(); echo "Всякие тексты"; header('Content-Type: text/plain; charset=windows-1251'); ?>
В этом случае никаких проблем не будет, т.к. ob_start() указывает, что данные вначале надо накапливать в буфере и отправлять браузеру только когда выполнение скрипта будет завершено.
Исправляем ошибку headers already sent by
От автора: в этом уроке мы рассмотрим, пожалуй, одну из наиболее распространенных ошибок, с которой сталкиваются при программировании на PHP. Эта ошибка возникает при работе с функциями, связанными с отправкой заголовков. При этом мы можем столкнуться с несколькими вариантами сообщений об ошибке, но причина у них будет одинакова – заголовки уже отправлены (headers already sent).
В видео версии урока вы найдете подробное описание вариантов возникновения данной ошибки. Здесь же мы сформулируем вкратце причины и способы решения данной ошибки.
Итак, ошибка эта может возникнуть в случаях, когда в коде вы используете одну из функций, связанных с отправкой заголовков: header(), session_start(), setcookie().
Курс «PHP-разработчик с нуля»
— Научитесь создавать сайты и веб-приложения на языке PHP.
— Изучите актуальные фреймворки Laravel, Simfony и Yii2.
— 78 часов теории и 361 час практики.
— Вы создадите 5 масштабных проектов для портфолио.
— Помощь с поиском работы или стажировки.
Курс «SQL и получение данных»
— Освоите один из основных инструментов работы с данными.
— 20 часов теории, 32 часа практики.
— Видеолекции, вебинары, практические задания и тренажёр.
— Выполните 6 домашних работ и итоговый проект.
— Помощь с поиском работы или стажировки.
Курс «веб-разработчик с нуля»
— Научитесь программировать на JavaScript и PHP.
— Сможете создавать сайты и веб-приложения.
— Сможете уверенно работать и с фронтендом, и с бэкендом веб-сервисов.
— Выполните 9 масштабных проектов для портфолио
— Помощь с поиском работы или стажировки.
Причина ошибки заключается в том, что перед данными функциями в коде где-то есть вывод в браузер. При этом выводом в браузер считается любой символ, даже пробел или перенос строки, которые можно увидеть в исходном коде.
Соответственно, решение проблемы заключается в том, что этот вывод нужно убрать. Варианты вывода могут быть следующими:
собственно вывод, который прописан в коде: это может быть пробел, перенос строки, HTML-код и т.д.
вывод в подключаемых файлах
сохранение документа в кодировке UTF-8 с BOM. Это наиболее неочевидная проблема и здесь стоит помнить, что при использовании юникода файл должен быть сохранен в кодировке UTF-8 без BOM.
На этом мы завершим текущий урок. Удачи и до новых встреч!
Cannot modify header information – headers already sent.
This is probably one of the most common PHP errors that you will come across as you struggle to come to grips with the intricate world of web development:
Cannot modify header information – headers already sent in (file location).
To sum this error up – It is basically telling you that you cannot output data before you attempt to modify header information. A quick example:
The code above will cause the error in question, simply because we attempted to change our header information after we had already printed out the string “Example” to the browser.
Common causes of this particular error are as follows:
- Attempting to modify header information after output has already been sent to the client (as seen in the code example above).
- Random whitespace and newline characters above the opening PHP tag.
- Whitespace after closing PHP tags in files that have been included at the top of the script.
- PHP errors causing error messages to be printed out onto the screen before the headers are modified.
- Attempting to modify header information after HTML has already been displayed.
An example of whitespace causing the “headers already sent” error:
Here, we can see that there is a blank line before our opening PHP tag. This blank line is interpreted as output by the server, resulting in the “headers already sent” error.
An example of HTML causing issues:
Our HTML is interpreted as being output, which prevents us from carrying out the intended redirect.
Debugging.
To debug this issue, you need to learn how to understand the warning message that PHP displays. Lets take the following example:
Warning: Cannot modify header information – headers already sent by (output started at /www/my-page.php:12) in /www/my-page.php on line 67
Here, we can see that PHP is telling us what the problem is being caused by LINE 12 in my-page.php. It is also telling us that our attempt to modify the header information failed on LINE 67 on my-page.php
Basically, the output on LINE 12 prevented our attempt to modify the header information on LINE 67.
Modifying Header Info.
There are a number of PHP functions that allow us to modify the HTTP header that the client receives. Popular examples include the functions header, session_start and setcookie. When using these functions, you MUST make sure that no output has been sent to the client beforehand.