- Вопрос или проблема
- Нет вывода перед отправкой заголовков!
- Почему это происходит?
- Как можно узнать, где произошел преждевременный вывод?
- Print, echo
- Сырые HTML зоны
- Пробел перед <?php для “скрипт.php строка 1” предупреждений
- UTF-8 BOM
- Утилиты для исправления
- Пробел после ?>
- Источник ошибки упоминается как “Неизвестная строка 0”
- Предшествующие сообщения об ошибках
- Нет сообщения об ошибке
- Буферизация вывода как обходной путь
- Но это работало на другом сервере!?
- Проверка с headers_sent()
- HTML <meta> тег
- JavaScript перенаправление
- Почему setcookie() и session_start() также подвержены этому
- Дополнительные ссылки
- КОММУНАЛЬНЫЕ ПРОБЛЕМЫ:
- Ответ или решение
- Как исправить ошибку "Заголовки уже отправлены" в PHP
- Причины возникновения ошибки
- Как обнаружить и исправить ошибки
- Другие рекомендации
Вопрос или проблема
При выполнении скрипта я получаю несколько ошибок, подобных этой:
Предупреждение: Невозможно изменить информацию заголовка – заголовки уже отправлены ((вывод начат на /some/file.php:12)) в /some/file.php на строке 23
Указанные в сообщениях об ошибках строки содержат header()
и setcookie()
.
В чем может быть причина этого? И как это исправить?
Нет вывода перед отправкой заголовков!
Функции, которые отправляют/изменяют HTTP-заголовки, должны вызываться до того, как будет осуществлен какой-либо вывод.
резюме ⇊
В противном случае вызов завершится неудачей:
Предупреждение: Невозможно изменить информацию заголовка – заголовки уже отправлены (вывод начат на скрипт:строка)
Некоторые функции, изменяющие HTTP-заголовки:
Вывод может быть:
-
Непреднамеренный:
- Пробел перед
<?php
или после?>
- UTF-8 Byte Order Mark конкретно
- Предыдущие сообщения об ошибках или уведомления
- Пробел перед
-
Преднамеренный:
print
,echo
и другие функции, создающие вывод- Сырые
<html>
секции перед<?php
кодом.
Почему это происходит?
Чтобы понять, почему заголовки должны отправляться перед выводом, необходимо взглянуть на типичный HTTP ответ. PHP-скрипты в основном генерируют HTML-контент, но также передают комплект HTTP/CGI заголовков на веб-сервер:
HTTP/1.1 200 OK
Powered-By: PHP/5.3.7
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
<html><head><title>Вывод PHP-страницы</title></head>
<body><h1>Содержимое</h1> <p>Следует еще немного вывода...</p>
и <a href="/"> <img src=internal-icon-delayed> </a>
Страница/вывод всегда следует за заголовками. PHP должен сначала передать заголовки на веб-сервер. Он может сделать это только один раз. После двойного разрыва строки он больше не сможет их изменить.
Когда PHP получает первый вывод (print
, echo
, <html>
), он сбрасывает все собранные заголовки. После этого он может отправить весь вывод, который хочет. Но дальнейшая отправка HTTP-заголовков невозможна.
Как можно узнать, где произошел преждевременный вывод?
Предупреждение header()
содержит всю актуальную информацию для поиска причины проблемы:
Предупреждение: Невозможно изменить информацию заголовка – заголовки уже отправлены (вывод начат на /www/usr2345/htdocs/auth.php:52) в /www/usr2345/htdocs/index.php на строке 100
Здесь “строка 100” ссылается на скрипт, где header()
вызов завершился неудачей.
Примечание “вывод начат на” в скобках более значимо. Оно обозначает источник предыдущего вывода. В этом примере это auth.php
и строка 52
. Вот где вам нужно искать преждевременный вывод.
Типичные причины:
-
Print, echo
Преднамеренный вывод из операторов
print
иecho
завершит возможность отправки HTTP-заголовков. Логика приложения должна быть структурирована так, чтобы избежать этого. Используйте функции и схемы шаблонов. Убедитесь, что вызовыheader()
происходят до записи сообщений.Функции, которые создают вывод, включают
print
,echo
,printf
,vprintf
trigger_error
,ob_flush
,ob_end_flush
,var_dump
,print_r
readfile
,passthru
,flush
,imagepng
,imagejpeg
среди прочих и пользовательских функций.
-
Сырые HTML зоны
Неразобранные HTML-секции в файле
.php
также являются прямым выводом. Условия сценария, которые вызовутheader()
, должны быть отмечены перед любыми сырыми<html>
блоками.<!DOCTYPE html> <?php // Для заголовков уже поздно.
Используйте схему шаблона, чтобы отделить обработку от логики вывода.
- Поместите код обработки форм поверх скриптов.
- Используйте временные строковые переменные, чтобы отложить сообщения.
- Настоящая логика вывода и смешанный HTML-вывод должны следовать последними.
-
Пробел перед
<?php
для “скрипт.php строка 1” предупрежденийЕсли предупреждение относится к выводу в строке
1
, то это в основном ведущий пробел, текст или HTML перед открывающим<?php
токеном.<?php # Здесь есть ОДИН пробел/перенос строки перед <? - что уже запечатывает его.
Аналогично это может произойти для добавленных скриптов или секций скриптов:
?> <?php
PHP на самом деле съедает один перенос строки после закрывающих тегов. Но он не компенсирует несколько новых строк или табуляций или пробелов, задвинутых в такие промежутки.
-
UTF-8 BOM
Переносы строк и пробелы сами по себе могут быть проблемой. Но также есть “невидимые” последовательности символов, которые могут вызвать это. Наиболее известный – UTF-8 BOM (Byte-Order-Mark), который не отображается в большинстве текстовых редакторов. Это последовательность байтов
EF BB BF
, которая является необязательной и избыточной для документов, закодированных в UTF-8. PHP, однако, должен рассматривать это как сырой вывод. Это может отображаться как символы
в выводе (если клиент интерпретирует документ как Latin-1) или похожий “мусор”.В частности графические редакторы и Java-IDE не обращают внимания на его присутствие. Они не визуализируют это (обязаны по стандарту Unicode). Однако большинство редакторов для программистов и консольных редакторов делают:
Здесь легко рано распознать проблему. Другие редакторы могут идентифицировать его присутствие в меню файлов/настроек (Notepad++ на Windows может определить и исправить проблему). Другой вариант – использовать hexeditor. В системах *nix
hexdump
обычно доступен, если нет, то графический вариант, который упрощает аудит этих и других проблем:Простое исправление – настроить текстовый редактор, чтобы сохранять файлы как “UTF-8 (без BOM)” или аналогично такой номенклатуре. Часто новички в противном случае создают новые файлы и просто копируют и вставляют предыдущий код обратно.
Утилиты для исправления
Также есть автоматизированные инструменты для проверки и переписывания текстовых файлов (
sed
/awk
илиrecode
). Специально для PHP естьphptags
утилита для очистки тегов. Она переписывает закрывающие и открывающие теги в длинные и короткие формы, но также легко исправляет ведущие и нарастающие пробелы, проблемы с Юникодом и BOM UTF-x:phptags --whitespace *.php
Безопасно использовать в целом для директории включений или проекта.
-
Пробел после
?>
Если источник ошибки упоминается за закрывающим
?>
, тогда это то место, где некоторые пробелы или сырой текст были выведены. Маркер конца PHP не завершает выполнение скрипта в этот момент. Любые текстовые/пробельные символы после него все равно будут выведены как содержимое страницы.Обычно советуется, особенно новичкам, что закрывающие теги PHP
?>
следует опустить. Это избавляет от небольшой доли таких случаев. (Довольно частоinclude()
скрипты являются виновниками.) -
Источник ошибки упоминается как “Неизвестная строка 0”
Это обычно настройки расширения PHP или php.ini, если источник ошибки не конкретизирован.
- Это время от времени может быть настройка кодирования потока
gzip
илиob_gzhandler
. - Но это также может быть любой дублированный загруженный
extension=
модуль, генерирующий явное сообщение о запуске/предупреждении PHP.
- Это время от времени может быть настройка кодирования потока
-
Предшествующие сообщения об ошибках
Если другой оператор PHP или выражение вызывает сообщение об ошибке или уведомление, которое выводится, это также считается преждевременным выводом.
В этом случае вам нужно избежать ошибки, отложить выполнение оператора или подавить сообщение с помощью, например,
isset()
или@()
– когда ни одно из них не мешает отладке позже.
Нет сообщения об ошибке
Если вы отключили error_reporting
или display_errors
в php.ini
, то никакое предупреждение не появится. Но игнорирование ошибок не избавит от проблемы. Заголовки все равно не могут быть отправлены после преждевременного вывода.
Поэтому, когда header("Location: ...")
перенаправления молча терпят неудачу, настоятельно рекомендуется проверить наличие предупреждений. Включите их заново с помощью двух простых команд сверху скрипта вызова:
error_reporting(E_ALL);
ini_set("display_errors", 1);
Или set_error_handler("var_dump");
, если все остальное не помогает.
Говоря о заголовках перенаправления, вы должны часто использовать идиому вроде этой для окончательных путей кода:
exit(header("Location: /finished.html"));
Предпочтительно даже использовать утилиту, которая выводит сообщение пользователю в случае неудач header()
.
Буферизация вывода как обходной путь
Буферизация вывода PHP это обходной путь для смягчения этой проблемы. Она часто работает надежно, но не должна заменять надлежащую структуру приложения и отделять вывод от логики управления. Ее фактическая цель – минимизация передач с разбивкой на части на веб-сервер.
-
Настройка
output_buffering=
тем не менее может помочь. Настройте ее в php.ini или через .htaccess или даже .user.ini на современных установках FPM/FastCGI.
Включение этого позволит PHP буферизовать вывод вместо того, чтобы передавать его на веб-сервер мгновенно. Таким образом, PHP может агрегировать HTTP-заголовки. -
Это также можно запустить с помощью вызова
ob_start();
в начале скрипта вызова. Однако это менее надежно по нескольким причинам:-
Даже если
<?php ob_start(); ?>
начинает первый скрипт, пробел или BOM могут быть перемещены вперед, делая это неэффективным. -
Это может скрыть пробел для HTML-вывода. Но как только логика приложения попытается отправить двоичный контент (например, сгенерированное изображение), буферизованный избыток вывода становится проблемой. (Требуя
ob_clean()
как еще одной обходной меры.) -
Буфер ограничен по размеру и может легко переполниться при оставлении по умолчанию. И это не редкое явление, трудно отследить, когда это происходит.
-
Обе подходы, таким образом, могут стать ненадежными – особенно при переключении между настройками разработки и/или серверами производства. Вот почему буферизация вывода широко рассматривается как просто костыль / строго обходной путь.
Смотрите также пример основного использования в руководстве, а также для более детального обсуждения плюсов и минусов:
- Что такое буферизация вывода в PHP?
- Почему использовать буферизацию вывода в PHP?
- Считается ли использование буферизации вывода плохой практикой?
- Пример использования буферизации вывода как правильного решения для “заголовков уже отправлено”
Но это работало на другом сервере!?
Если вы ранее не получали предупреждение заголовков, то настройка буферизации вывода php.ini изменилась. Вероятно, она не настроена на текущем/новом сервере.
Проверка с headers_sent()
Вы всегда можете использовать headers_sent()
, чтобы определить, возможно ли еще… отправить заголовки. Это полезно для условного вывода информации или применения другой логики подстраховки.
if (headers_sent()) {
die("Перенаправление не удалось. Пожалуйста, нажмите на эту ссылку: <a href=...>");
}
else{
exit(header("Location: /user.php"));
}
Полезные обходные пути:
-
HTML
<meta>
тегЕсли ваша структура приложения трудно исправить, то простой (но несколько непрофессиональный) способ разрешить перенаправления – внедрить HTML
<meta>
тег. Перенаправление можно достичь следующим образом:<meta http-equiv="Location" content="http://example.com/">
Или с короткой задержкой:
<meta http-equiv="Refresh" content="2; url=../target.html">
Это ведет к недействительному HTML, когда используется после секции
<head>
. Тем не менее, большинство браузеров это принимают. -
JavaScript перенаправление
В качестве альтернативы можно использовать JavaScript перенаправление для перенаправлений страниц:
<script> location.replace("target.html"); </script>
Хотя это часто более соответствуют HTML, чем обходной путь
<meta>
, это накладывает зависимость от клиентов, способных работать с JavaScript.
Тем не менее, оба подхода делают приемлемые подстраховки, когда реальные вызовы HTTP заголовка() терпят неудачу. В идеале вы всегда должны комбинировать это с дружелюбным сообщением и кликабельной ссылкой в качестве последнего средства. (Что, например, делает http_redirect() PECL расширение.)
Почему setcookie()
и session_start()
также подвержены этому
Оба setcookie()
и session_start()
должны отправлять заголовок Set-Cookie:
HTTP. Поэтому те же условия применяются, и подобные сообщения об ошибках будут генерироваться для ситуаций преждевременного вывода.
(Естественно, они также подвержены отключенным cookie в браузере или даже проблемам с прокси. Функциональность сессии, очевидно, также зависит от свободного места на диске и других настроек php.ini и т. д.)
Дополнительные ссылки
- Google предоставляет длинный список аналогичных обсуждений.
- И, конечно, много конкретных случаев также обсуждалось на Stack Overflow.
- Часто задаваемые вопросы WordPress объясняют Как я решаю проблему предупреждения “Заголовки уже отправлены”? в обобщенной манере.
- Сообщество Adobe: PHP разработка: почему перенаправления не работают (заголовки уже отправлены)
- FAQ Nucleus: Что значит “заголовки страницы уже отправлены”?
- Одно из более подробных объяснений HTTP-заголовки и функция PHP header() – учебное пособие от NicholasSolutions (ссылка на Интернет-архив). Оно подробно охватывает HTTP и дает несколько рекомендаций по переписыванию скриптов.
Это сообщение об ошибке возникает, когда что угодно отправляется перед тем, как вы отправите HTTP-заголовки (с помощью setcookie
или header
). Обычные причины вывода чего-либо перед HTTP-заголовками следующие:
-
Случайные пробелы, часто в начале или в конце файлов, например:
<?php // Обратите внимание на пробел перед "<?php" ?>
Чтобы избежать этого, просто не указывайте закрывающий ?>
– он и не нужен.
- Маркировки порядка байтов в начале php файла. Проверьте свои php файлы с помощью hex-редактора, чтобы выяснить, так ли это. Они должны начинаться с байтов
3F 3C
. Вы можете безопасно удалить BOMEF BB BF
из начала файлов. - Явный вывод, такой как вызовы
echo
,printf
,readfile
,passthru
, код перед<?
и т. д. - Предупреждение, полученное php, если параметр
display_errors
в php.ini установлен. Вместо того, чтобы сбоить из-за ошибки программиста, php тихо исправляет ошибку и выдает предупреждение. Хотя вы можете изменить конфигурацииdisplay_errors
или error_reporting, лучше исправить проблему.
Обычные причины – доступ к неопределенным элементам массива (например,$_POST['input']
без использованияempty
илиisset
для проверки назначения ввода) или использование неопределенной константы вместо строкового литерала (как в$_POST[input]
, обратите внимание на отсутствие кавычек).
Включение буферизации вывода должно устранить проблему; весь вывод после вызова ob_start
буферизуется в памяти до тех пор, пока вы не освободите буфер, например с помощью ob_end_flush
.
Однако, хотя буферизация вывода избегает проблем, вам действительно нужно выяснить, почему ваше приложение выводит HTTP-тело перед HTTP-заголовком. Это было бы все равно, что принять телефонный звонок и обсудить свой день и погоду перед тем, как сказать звонящему, что он ошибся номером.
Я получал эту ошибку много раз раньше, и я уверен, что все программисты PHP сталкивались с этой ошибкой, по крайней мере, однажды.
Возможное решение 1
Эта ошибка может быть вызвана пробелами перед началом файла или после конца файла. Эти пробелы не должны быть здесь.
например)
<!-- ЗДЕСЬ НИКАКИХ ПРОБЕЛОВ НЕ ДОЛЖНО БЫТЬ -->
<?php
echo "ваш код здесь";
?>
<!-- ЗДЕСЬ НИКАКИХ ПРОБЕЛОВ НЕ ДОЛЖНО БЫТЬ -->
Проверьте все файлы, связанные с файлом, который вызывает эту ошибку.
Примечание: Иногда РЕДАКТОР(IDE), такой как gedit
(стандартный редактор Linux), добавляет одну пустую строку при сохранении файла. Этого не должно происходить. Если вы используете Linux, вы можете использовать редактор VI, чтобы удалить пробелы/строки после ?>
в конце страницы.
Возможное решение 2: если это не ваш случай, то используйте ob_start для буферизации вывода:
<?php
ob_start();
// код
ob_end_flush();
?>
Это включит буферизацию вывода, и ваши заголовки будут созданы после буферизации страницы.
Вместо следующей строки
//header("Location:".ADMIN_URL."/index.php");
напишите
echo "<script>location.href='https://stackoverflow.com/questions/79070898/'".ADMIN_URL."/index.php?msg=$msg';</script>";
или
?><script><?php echo "location.href='https://stackoverflow.com/questions/79070898/'".ADMIN_URL."/index.php?msg=$msg';";?></script><?php
Это определенно решит вашу проблему. Я столкнулся с той же проблемой, но решил ее, записав местоположение заголовка таким образом.
Это обычно происходит, когда есть непреднамеренный вывод из скрипта перед началом сессии. С вашим текущим кодом вы можете попробовать использовать буферизацию вывода, чтобы решить проблему.
Попробуйте добавить вызов функции ob_start();
в самом начале вашего скрипта и ob_end_flush();
в самом конце документа.
Вы делаете
printf ("Привет %s,</br />", $name);
перед установкой куки, что не разрешается. Нельзя отправлять никакой вывод перед заголовками, даже пустую строку.
КОММУНАЛЬНЫЕ ПРОБЛЕМЫ:
1) не должно быть никакого вывода (т.е. echo..
или HTML-коды) перед командой header(.......);
.
2) уберите любые пробелы(или переносы строк) перед <?php
и после ?>
тегов.
3) ЗОЛОТАЯ ПРАВИЛО! – проверьте, имеет ли этот php-файл (а также, если вы include
другие файлы) UTF8 без BOM кодировки (а не просто UTF-8). Это проблема во многих случаях (поскольку UTF8 закодированный файл имеет что-то специальное в начале php-файла, что ваш текстовый редактор не показывает)!!!!!!!!!!!
4) После header(...);
вы должны использовать exit;
5) всегда используйте 301 или 302 ссылки:
header("location: http://example.com", true, 301 ); exit;
6) Включите отображение ошибок и найдите ошибку. Ваша ошибка может быть вызвана функцией, которая не работает. Когда вы включаете отображение ошибок, вы всегда должны исправлять первую ошибку. Например, это может быть “Предупреждение: date_default_timezone_get(): нельзя полагаться на настройки часового пояса системы.” – а затем позже вы можете увидеть “заголовки не отправлены” ошибку. После исправления самой верхней (первой) ошибки перезагрузите страницу. Если у вас все еще есть ошибки, снова исправьте самую верхнюю ошибку.
7) Если ни одно из вышеперечисленного не помогает, используйте перенаправление JAVSCRIPT (хотя это строго не рекомендуется), может быть последним шансом в индивидуальных случаях…:
echo "<script type='text/javascript'>window.top.location='http://website.com/';</script>"; exit;
Строки 45-47:
?>
<?php
Это отправляет несколько переносов строк в качестве вывода, поэтому заголовки уже отправлены. Просто уберите эти 3 строки (все это один большой блок PHP, в конце концов, нет необходимости закрывать PHP-парсинг, а затем снова начинать), а также аналогичный блок на строках 60-62, и все будет работать.
Заметьте, что сообщение об ошибке, которое вы получили, на самом деле дает вам много информации, чтобы помочь вам найти это самостоятельно:
Предупреждение: Невозможно изменить информацию заголовка – заголовки уже отправлены (вывод начат на C:\xampp\htdocs\speedycms\deleteclient.php:47) в C:\xampp\htdocs\speedycms\deleteclient.php на строке 106
Две выделенные секции говорят вам, где предмет, который отправил вывод перед заголовками (строка 47) и где предмет, который пытался отправить заголовок после вывода (строка 106).
Это происходит из-за этой строки:
printf ("Привет %s,</br />", $name);
Вы не должны печать/выводить ничего до отправки заголовков.
Простой совет: простой пробел (или невидимый специальный символ) в вашем скрипте, прямо перед самым первым <?php
тегом, может вызвать это! Особенно, когда вы работаете в команде, и кто-то использует “слабый” IDE или каким-то образом испортил файлы странными текстовыми редакторами.
Я видел такие вещи 😉
Проверьте кодировку документа.
У меня была такая же проблема. Я разработал это на Windows XP, используя Notepad++ и WampServer для локального запуска Apache, и все было в порядке. После загрузки на хостинг-провайдер, который использует Apache на Unix, я получил эту ошибку. У меня не было дополнительных PHP тегов или пробелов от дополнительных строк после закрывающего тега.
Для меня это было вызвано кодировкой текстовых документов. Я использовал опцию “Преобразовать в UTF-8 без BOM” в Notepad++ (в вкладке Кодировка) и перезагрузил на веб-сервер. Проблема была решена, изменения в коде/редактировании не требовались.
Еще одна плохая практика может вызвать эту проблему, о которой еще не говорилось.
Смотрите этот фрагмент кода:
<?php
include('a_important_file.php'); //очень-очень плохая практика
header("Location:A location");
?>
Вроде все в порядке, правда?
Что, если “a_important_file.php” это:
<?php
//некоторый PHP код
//другая строка кода PHP
//ни одна строка выше не генерирует никакого вывода
?>
----------Это конец an_important_file-------------------
Так не получится? Почему? Потому что уже сгенерирована новая строка.
Теперь, хотя это не распространенный сценарий, что, если вы используете фреймворк MVC, который загружает много файлов перед передачей управления вашему контроллеру? Это не редкий сценарий. Будьте готовы к этому.
Из PSR-2 2.2 :
- Все PHP файлы ДОЛЖНЫ использовать
Unix LF (перевод строки) окончание строки
. - Все PHP файлы ДОЛЖНЫ заканчиваться
одной пустой строкой
. - Закрывающий ?> тег ДОЛЖЕН быть
опущен
из файлов, содержащихтолько php
Поверьте, соблюдение этих стандартов может сэкономить вам много часов жизни 🙂
Иногда, когда процесс разработки включает как WIN рабочие станции, так и LINUX системы (хостинг), и в коде вы не видите никакого вывода перед соответствующей строкой, это может быть связано с форматированием файла и отсутствием Unix LF (перевод строки) окончания строки.
Что мы обычно делаем, чтобы быстро это исправить, так это переименовываем файл и на LINUX системе создаем новый файл вместо переименованного, а затем копируем содержимое в него. Часто это решает проблему, поскольку некоторые из файлов, созданных в WIN, после перемещения на хостинг вызывают эту проблему.
Это исправление – простой способ для сайтов, которыми мы управляем по FTP, и иногда может сэкономить время нашим новым членам команды.
Скорее всего, пробел находится за пределами ваших php тегов.
Эти пустые строки между вашими ?>
и <?php
тегами отправляются клиенту.
Когда первый из них отправляется, это приводит к тому, что ваши заголовки отправляются первыми.
Как только это происходит, вы больше не можете изменять заголовки.
Удалите эти ненужные теги, соберите все в один большой <?php
блок.
Как правило, эта ошибка возникает, когда мы отправляем заголовок после вывода или печати. Если эта ошибка возникает на конкретной странице, тогда убедитесь, что эта страница не выводит ничего перед вызовом start_session()
.
Пример непредсказуемой ошибки:
<?php //пробел перед <?php также отправляет вывод и вызывает ошибку
session_start();
session_regenerate_id();
//ваш контент страницы
Еще один пример:
<?php
includes 'functions.php';
?> <!-- Эта новая строка также вызовет ошибку -->
<?php
session_start();
session_regenerate_id();
//ваш контент страницы
Вывод: Не выводите никакой символ перед вызовом session_start()
или header()
функций, даже пробел или новой строки
Ответ или решение
Как исправить ошибку "Заголовки уже отправлены" в PHP
Ошибка "Headers already sent" возникает, когда вы пытаетесь отправить HTTP заголовки после того, как уже был выведен какой-либо контент на страницу. Это может произойти из-за различных причин, и в этой статье мы разберем возможности устранения данной проблемы.
Причины возникновения ошибки
-
Неправильное расположение пробелов или выходных данных: Обычно ошибка возникает, если перед открывающим тегом
<?php
или после закрывающего тега?>
есть лишние пробелы или символы. Эти символы рассматриваются PHP как отправляемый контент, что мешает последующей отправке заголовков.<!-- Не должно быть пробелов перед началом PHP --> <?php header("Location: http://example.com"); ?>
-
Байтовая марка порядка (BOM): Если ваш PHP файл сохранен с байтовой меткой порядка UTF-8 (BOM), то эти невидимые символы могут предшествовать выводу и вызывать проблему. Используйте текстовые редакторы, такие как Notepad++ или Sublime Text, чтобы сохранить файлы в "UTF-8 без BOM".
-
Явное или неявное создание вывода: Функции, такие как
echo
,print
,var_dump
,printf
, создают вывод. Если они вызываются передheader()
илиsetcookie()
, это вызывает ошибку. -
Ошибки и предупреждения: Если в вашем коде имеются ошибки и выводятся предупреждения, это считается выходом, поэтому обязательно следите за тем, чтобы не было выводимых сообщений перед отправкой заголовков.
Как обнаружить и исправить ошибки
-
Проверка вывода: Проверьте, нет ли лишних символов перед открывающим тегом
<?php
и после закрывающего тега?>
. Рекомендуется не использовать закрывающий тег в файлах, содержащих только PHP, чтобы избежать этой ситуации.<?php // Ваш PHP код // Не используйте закрывающий тег
-
Очистка исходного кода от BOM: Если вы используете редакторы, которые могут добавлять BOM, убедитесь, что сохраняете файл в формате "UTF-8 без BOM".
-
Включение и отключение вывода: Если обнаруживается, что проблема сохраняется, попробуйте использовать буферизацию вывода с помощью функций
ob_start()
иob_end_flush()
. Это позволит временно сохранять вывод до вызова заголовков.<?php ob_start(); // Начать буферизацию вывода header("Location: http://example.com"); // Отправить заголовок ob_end_flush(); // Вывести буферизированный вывод
-
Проверка ошибок: Включите отображение ошибок в PHP, чтобы отследить все возникающие проблемы:
ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
Другие рекомендации
-
Структурирование кода: Избегайте смешивания логики обработки и вывода. Разделяйте код, который генерирует данные, от тех частей, что выводят HTML.
-
Используйте HTML и JavaScript перенаправления: Если возникла ситуация, когда необходимо сделать перенаправление, а отправка заголовков невозможна, в качестве альтернативы можно использовать JavaScript:
<script> window.location.href = "http://example.com"; </script>
-
Изучите использование функций, таких как
headers_sent()
: Это функция позволяет проверить, были ли уже отправлены заголовки, и вы можете использовать её для отладки.
Следуя этим рекомендациям, вы сможете устранить ошибку "Headers already sent" и избежать её повторного возникновения в будущем.