- Как исправить ошибку «Заголовки уже отправлены» в PHP
- 11 ответов
- Нет вывода перед отправкой заголовков!
- Почему это происходит?
- Как узнать, где произошел преждевременный выход?
- Печать, эхо
- Необработанные области HTML
- Пробелы перед строка 1» предупреждения
- Спецификация UTF-8
- Утилиты исправления
- Пробелы после ?>
- Источник ошибки, указанный как «Неизвестно в строке 0»
- Предыдущие сообщения об ошибках
- Нет сообщения об ошибке
- Буферизация вывода в качестве обходного пути
- Но он работал на другом сервере!?
- Проверка с помощью headers_sent()
- HTML тег
- Переадресация JavaScript
- Почему setcookie() и session_start() также затронуты
- Дальнейшие ссылки
Как исправить ошибку «Заголовки уже отправлены» в PHP
Линии, упомянутые в сообщениях об ошибках, содержат header() и setcookie() . Что может быть причиной этого? И как это исправить?
Убедитесь, что текст не выводится ( ob_start и ob_end_clean() могут оказаться здесь полезными). Затем вы можете установить cookie или сеанс, равный ob_get_contents() а затем использовать ob_end_clean() для очистки буфера.
11 ответов
Нет вывода перед отправкой заголовков!
Функции, отправляющие/изменяющие HTTP-заголовки, должны быть вызваны до того, как будет выполнен какой-либо вывод. резюме В противном случае вызов завершается с ошибкой:
Предупреждение: невозможно изменить информацию заголовка — уже отправленные заголовки (вывод начался с script: строка)
Некоторые функции, изменяющие HTTP-заголовок:
- Unintentional:
- Пробелы перед
- Обозначение порядка байтов UTF-8
- Предыдущие сообщения об ошибках или уведомления
- Преднамеренное:
- print , echo и другие функции, производящие вывод
- Необработанные разделы, предшествующие
Почему это происходит?
Чтобы понять, почему заголовки должны быть отправлены перед выходом, необходимо посмотреть типичный 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
Content
Some more output follows.
andСтраница/вывод всегда следует за заголовками. PHP должен пройти сначала создайте заголовки на веб-сервере. Это может сделать только один раз. После двойной линии он никогда не может изменить их.
Когда PHP получает первый вывод ( print , echo , ), он будет очистить все собранные заголовки. Впоследствии он может отправить весь вывод он хочет. Но отправка последующих HTTP-заголовков невозможна.
Как узнать, где произошел преждевременный выход?
Предупреждение header() содержит всю соответствующую информацию для найти причину проблемы:
Предупреждение: невозможно изменить информацию заголовка — заголовки, уже отправленные (вывод начинается с/www/usr2345/htdocs/ auth.php: 52) в /www/usr 2345/htdocs/index.php в строке 100
Здесь «строка 100» относится к script, где не удалось выполнить вызов header() .
Заметка «вывод, начатая с» в круглой скобке более значительна. Он обозначает источник предыдущего вывода. В этом примере это auth.php и строка 52 . Это то, где вам приходилось искать преждевременный выход.
Печать, эхо
- print , echo , printf , vprintf
- trigger_error , ob_flush , ob_end_flush , var_dump , print_r
- readfile , passthru , flush , imagepng , imagejpeg
и т.д. и пользовательские функции.
Необработанные области HTML
Необработанные разделы HTML в файле .php также являются прямым выходом. Script должны быть отмечены условия, вызывающие вызов header() перед любыми необработанными блоками .
- Обработать код обработки формы на скриптах поверх.
- Используйте временные строковые переменные для отсрочки сообщений.
- Фактическая логика вывода и смешанный вывод HTML должны соответствовать последним.
Пробелы перед строка 1» предупреждения
Если предупреждение относится к выходу в строке 1 , то это в основном пробелы, текст или HTML перед открывающим токеном
Спецификация UTF-8
Одной из проблем может быть только односторонняя линия и пространство. Но есть и «невидимые» последовательности символов, которые могут вызвать это. Самый классный Спецификация UTF-8 (байт-заказ-марка)который не отображается большинством текстовых редакторов. Это байтовая последовательность EF BB BF , которая является необязательным и избыточным для кодированных документов UTF-8. Однако PHP должен лечить это как сырой выход. Он может отображаться как символы  на выходе (если клиент интерпретирует документ как латинский-1) или аналогичный «мусор». В частности, графические редакторы и Java-IDE не обращают внимания на свои присутствие. Они не визуализируют его (обязаны стандартом Unicode). Однако большинство программистов и консольных редакторов: Там легко понять проблему на ранней стадии. Другие редакторы могут идентифицировать его присутствие в меню файлов/настроек (Notepad ++ в Windows может идентифицировать и устранить проблему), Другой способ проверки присутствия BOM прибегает к hexeditor. В системах * nix hexdump обычно доступен, если не графический вариант, который упрощает проверку этих и других проблем: Легкое исправление заключается в том, чтобы установить текстовый редактор для сохранения файлов как «UTF-8 (no BOM)» или подобная такая номенклатура. Зачастую новички прибегают к созданию новых файлы и просто скопировать и снова вставить предыдущий код.
Утилиты исправления
Существуют также автоматизированные инструменты для проверки и перезаписи текстовых файлов ( sed / awk или recode ). Для PHP специально существует phptags tag tidier. Он переписывает закрытые и открытые теги в длинные и короткие формы, но также легко исправляет начальные и конечные пробелы, проблемы с Unicode и UTF-x:
Пробелы после ?>
Источник ошибки, указанный как «Неизвестно в строке 0»
- Иногда параметр настройки потока gzip или ob_gzhandler .
- Но это может быть и любой загруженный в два раза модуль extension= генерирование неявного сообщения о запуске/предупреждении PHP.
Предыдущие сообщения об ошибках
Нет сообщения об ошибке
Если у вас error_reporting или display_errors отключено на php.ini , то предупреждение не появится. Но игнорирование ошибок не вызовет проблемы далеко. Заголовки по-прежнему не могут быть отправлены после преждевременного выхода.
Поэтому, когда header(«Location: . «) перенаправляет молча, рекомендуется проконтролировать предупреждения. Обозначить их двумя простыми командами на вызов script:
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 on современные установки FPM/FastCGI.
Включение этого режима позволит PHP выводить выходные данные вместо того, чтобы передавать его на веб-сервер мгновенно. Таким образом, PHP может собирать заголовки HTTP. - Он также может быть связан с вызовом ob_start(); на вершине вызова script. Это, однако, менее надежно по нескольким причинам:
- Даже если запускает первый script, пробел или Спецификация может быть перетасована раньше, делает ее неэффективной.
- Он может скрывать пробелы для вывода HTML. Но как только приложение логические попытки отправить двоичный контент (например, сгенерированное изображение), буферизованный посторонний выход становится проблемой. (Необходимость ob_clean() как предыдущий вариант.)
- Буфер ограничен по размеру и может быть легко переполнен, если оставить его по умолчанию. И это не редкость, трудно отследить когда это произойдет.
Оба подхода могут стать ненадежными — в частности, при переключении между разработки и/или производственные серверы. Именно поэтому буферизация вывода широко считается просто костылем/строго обходным путем.
См. также базовый пример использования в руководстве, и для большего количества плюсов и минусов:
Но он работал на другом сервере!?
Если вы не получили предупреждения заголовков раньше, то выходная буферизация Настройка php.ini изменилось. Вероятно, он не сконфигурирован на текущем/новом сервере.
Проверка с помощью headers_sent()
Вы всегда можете использовать headers_sent() , чтобы проверить, если все еще можно. отправить заголовки. Что полезно для условной печати информацию или применить другую резервную логику.
HTML тег
Если ваше приложение структурно сложно исправить, тогда простое (но несколько непрофессиональный) способ разрешить переадресацию — это инъекция HTML-кода тег . Перенаправление может быть достигнуто с помощью:
Переадресация JavaScript
Оба подхода, однако, делают приемлемые резервные копии, когда подлинный HTTP-заголовок() вызовы не выполняются. В идеале вы всегда должны сочетать это с удобным для пользователя сообщением и в качестве последней инстанции. (Например, это http_redirect() Расширение PECL делает.)
Почему setcookie() и session_start() также затронуты
Оба setcookie() и session_start() должны отправить HTTP-заголовок Set-Cookie: . Таким образом, применяются те же условия, и аналогичные сообщения об ошибках будут сгенерированы для случаев преждевременного выхода.
(Конечно, в браузере, кроме того, они подвержены воздействию файлов cookie, или даже проблемы с прокси. Функциональность сеанса, очевидно, также зависит от дисковое пространство и другие настройки php.ini и т.д.)
Дальнейшие ссылки
- Google предоставляет длинный список подобных обсуждений.
- И, конечно, многие конкретные случаи были также рассмотрены в переполнении стека.
- В WordPress часто задаются вопросы Как решить проблему, уже отправленную предупреждением? в общем виде.
- Сообщество Adobe: PHP-разработка: почему перенаправления не работают (уже отправленные заголовки)
- Часто задаваемые вопросы о нуклеусе: Что означает «заголовки страниц уже отправлены» ?
- Одним из более подробных объяснений является HTTP-заголовки и функция заголовка PHP() — учебник NicholasSolutions (ссылка на интернет-архив). Он подробно описывает HTTP и дает несколько рекомендаций по переписыванию скриптов.
Также обычный notepad.exe сложно. Я обычно использую NetBeans, который не добавляет спецификацию, даже если файл закодирован так. Редактирование файла позже в блокноте приводит к путанице, особенно к IIS как веб-серверу. Кажется, что apache отбрасывает (добавленную единицу) спецификацию.
Удаление закрывающего ?> Из конца php-файлов обычно является хорошей практикой, которая также помогает минимизировать эти ошибки. Нежелательные пробелы не будут появляться в конце файлов, и вы все равно сможете добавить заголовки к ответу позже. Это также удобно, если вы используете буферизацию вывода и не хотите видеть добавленные нежелательные пробелы в конце частей, сгенерированных включенными файлами.
Странно, я переместил свой файл с хостинга cPanel Linux на VPS. До того, как он работал правильно, но здесь он показал эту ошибку. (У меня был HTML-код перед заголовком). Зачем?