#Что означает ошибка
Warning: Cannot modify header information — headers already sent
«Warning: Cannot modify header information — headers already sent by (output started at файл:строка)» означает, что PHP уже начал выводить содержимое страницы, а затем пытается отправить HTTP-заголовок (header(), setcookie(), session_start()). Заголовки должны идти строго до любого вывода.
Сообщение само указывает, где начался вывод: output started at /path/file.php:12.
Проблему вызывает любой символ перед <?php: пробел, пустая строка, BOM.
Заголовки нельзя отправить, если уже был вывод: пробелы перед <?php, BOM, echo. Уберите вывод до header().
#Причины и решения
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Пробел перед <?phpФайл. | Ошибка. | Удалите. |
| BOMUTF-8 BOM. | Ошибка. | Сохраните без BOM. |
| Ранний echoВывод. | Ошибка. | Уберите. |
| Закрывающий ?>Пробелы. | Ошибка. | Удалите. |
#Пошаговое решение
- Откройте файл и строку из сообщенияВ полном предупреждении PHP найдите две части:
output started at /путь/файл.php:строкаиheaders already sent in /путь/другой.php:строка. Откройте редактором именно первый файл по указанной строке; там вывод появился раньшеheader(),setcookie()либоsession_start(). Перед правкой сохраните копию файла, а журнал с путями не публикуйте открыто. - Уберите лишние пробелы и
?>в конце файлаПросмотрите начало подключённых PHP-файлов: перед<?phpне должно быть пробелов, HTML или случайного вывода, если затем требуется отправлять HTTP-заголовки. В чистых PHP-файлах рекомендуется не добавлять закрывающий?>, чтобы случайный перенос строки не выводился в ответ. Сохраните файл и снова воспроизведите запрос. - Сохраните без BOMЕсли файл начинается с BOM, откройте его в редакторе, который показывает кодировку (например, VS Code: индикатор кодировки в строке состояния). Выберите сохранение в «UTF-8» без BOM, предварительно убедившись, что приложение рассчитано на UTF-8. Команда
head -c 3 файл | xxdпомогает обнаружить байты EF BB BF; не перекодируйте всю базу и весь сайт ради одного файла. - Перенесите header() и session_start()В точке входа PHP расположите вызовы
session_start(),setcookie()иheader("Location: ...")до HTML,echo, отладочногоvar_dumpи включения шаблона, где есть вывод. После редиректа используйтеexit;, если дальнейший вывод не нужен. Проверьте, что требуемые заголовки появились через инструменты разработчика браузера → «Сеть» → нужный запрос. - При необходимости включите буферизацию
ob_start()можно применять только как осознанное управление буферизацией, но не как замену исправления раннего вывода. Если проекту нужен буфер, добавляйте его до любого вывода в точке входа и проверяйте, что он не скрывает ошибку и не ломает потоковые ответы. При повторении предупреждения найдите новыйoutput started atи устраните именно тот источник.
#Как найти источник
Откройте файл и строку из output started at. Проверьте: пробел или перевод строки перед <?php или после закрывающего ?>; BOM в начале файла (сохраните в UTF-8 без BOM — в VS Code внизу «UTF-8 with BOM» → «Save with Encoding» → UTF-8); echo, print или HTML выше вызова header(). Проверка BOM: head -c 3 файл.php | xxd — не должно быть efbbbf.
#Типичные решения
Уберите закрывающий ?> в конце чисто PHP-файлов — это безопасно и предотвращает случайные пробелы. Перенесите header(), setcookie() и session_start() в самое начало. Если логика сложная, включите буферизацию вывода: ob_start(); в начале скрипта или output_buffering = 4096 в php.ini. Это обходной путь, но он безопасен на проде.
#Файлы в CMS и шаблонах
В WordPress и Joomla проблему часто вызывает пробел в wp-config.php, functions.php или в плагине после ?>. Включите отладку: define('WP_DEBUG', true);, посмотрите путь из сообщения и исправьте файл. Если отредактировали файл на Windows в «Блокноте», пересохраните его в редакторе с поддержкой UTF-8 без BOM ().
#Проверка всего проекта
Найдите файлы с BOM: grep -rl $'\xEF\xBB\xBF' --include=*.php . и файлы, где ?> заканчивается переводом строки: grep -rlPz "\?>\s+\z" --include=*.php .. Эти команды покажут «подозреваемых» разом.
grep -rl $'\xEF\xBB\xBF' --include=*.php .head -c 3 index.php | xxd