#Что означает ошибка
headers already sent
HTTP-заголовки (в том числе cookie и редиректы) отправляются перед телом ответа. Как только PHP отправил первый байт содержимого, изменять заголовки поздно. Сообщение обычно содержит подсказку: (output started at /var/www/site/config.php:3) — файл и строка, где вывод начался. Начинайте именно с неё.
#Причины и решения
| Возможная причина | Как узнать | Что делать |
|---|---|---|
Пробелы или перевод строки до <?phpВ начале файла есть пустая строка или пробел. | output started at ... :1. | Удалите всё перед <?php. |
| BOM в файлеРедактор сохранил UTF-8 с BOM, и перед кодом выводятся три байта. | В журнале :1, пробелов не видно. | Сохраните UTF-8 без BOM. |
echo, print или HTML до headerВывод идёт раньше вызова header(). | Строка с echo перед редиректом. | Переместите header() выше или используйте буфер. |
Закрывающий ?> с пробелом послеПосле ?> в include-файле остался перевод строки. | Ошибка указывает на последнюю строку include. | Уберите ?> в конце файлов с кодом. |
#Пошаговое решение
- Прочитайте сообщение целикомСкопируйте текст предупреждения целиком: важна часть
output started at /путь/файл.php:строка. Первый указанный файл и строка — место, где PHP начал вывод; путь кheader()илиsetcookie()обычно указывается позже. На копии проекта откройте первый файл в редакторе, перейдите к строке и посмотрите не только наecho, но и на HTML, пробелы, включённые шаблоны и сообщения об ошибках. Проблема не в недоступности сайта, а в том, что HTTP-заголовки уже были отправлены клиенту. - Откройте файл из «output started at»Если предупреждение указывает на начало PHP-файла, откройте его в VS Code и проверьте самый первый символ: в чистом PHP-файле до
<?phpне должно быть HTML, пробела или перевода строки. В файле-шаблоне HTML до PHP может быть намеренным — тогда переместите установку заголовков раньше, а не удаляйте верстку. Убедитесь, что файл сохранён в UTF-8 без BOM. После изменения повторите запрос и проверьте, что предупреждение исчезло и страница работает корректно. - Проверьте BOMДля проверки BOM откройте в VS Code проблемный PHP-файл, нажмите по надписи кодировки в строке состояния и выберите «Сохранить с кодировкой → UTF-8». Перед сохранением убедитесь, что это именно UTF-8 без BOM, и сохраните резервную копию, если на сайте старые файлы используют Windows-1251. В Linux можно проверить первые три байта командой
head -c 3 index.php | xxd: последовательностьef bb bfуказывает на BOM, но не доказывает, что именно этот файл виновен. Не перекодируйте весь сайт автоматически. - Уберите закрывающий ?>В файле, содержащем только PHP-код, найдите закрывающий
?>в конце и удалите его, если после него выводятся случайные пробелы или пустые строки. Не удаляйте обязательный закрывающий тег в шаблонах, где далее расположен HTML. Изменение проверьте на копии и откройте соответствующую страницу. Если HTML уже выведен до выполнения кода, удаление?>ничего не исправит: переходите к корректировке порядка обработки запроса. - Переместите вызов headerНайдите вызовы
header(),setcookie()иsession_start()с помощью поиска по проекту в редакторе. Перенесите их в обработчик запроса до первого вывода (echo, печати шаблона или HTML), сохраняя зависимость от проверок авторизации. Послеheader('Location: ...')обычно нуженexit;, чтобы код не продолжал формировать страницу. Проверьте в инструментах разработчика браузера вкладку Network → конкретный запрос → Response Headers: код ответа, Location и Set-Cookie должны соответствовать ожидаемому поведению. - Используйте буферизациюЕсли архитектуру приложения быстро изменить нельзя, буферизация
ob_start()до вывода может временно отложить отправку заголовков, но это не исправляет ошибочную последовательность действий. Сначала проверьте, не запускает ли фреймворк собственную буферизацию, и не делает ли кодflush()/ob_end_flush()раньше времени. Менятьoutput_bufferingна всём сервере ради одной страницы не стоит. Сделайте изменение в испытательной среде, затем проверьте редиректы и сеансы; если сбой остаётся, вернитесь к порядку формирования ответа. - Включите показ ошибок на время отладкиДля диагностики на рабочем сайте не включайте
display_errors=1: появляющиеся предупреждения могут отправить вывод и усугубить проблему, а посетители увидят внутренние пути. Настройте запись ошибок в защищённый журнал средствами панели управления PHP, затем воспроизведите запрос и сравните время со строками журнала. На испытательном экземпляре можно включить подробные сообщения, но не публиковать их наружу. После исправления проверьте вход пользователя, отправку cookie и переадресацию; если заголовки отсутствуют, соберите путь и строку первого вывода для разработчика. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
В WordPress ошибка чаще всего вызвана пробелом в конце wp-config.php или functions.php темы, либо плагином, который выводит текст при активации. Отключите плагины переименованием папки wp-content/plugins и проверьте. После исправления не забудьте выключить вывод ошибок на рабочем сайте: display_errors = Off. Подробности — .