Сегодня я хочу рассказать вам об одной очень популярной и загадочной ошибке. Наверняка, многие из вас во время отладки своих программ сталкивались со следующим сообщением: headers already sent. Переводится на русский язык данная запись как «заголовки уже отправлены».
Чтобы понять суть этой ошибки, давайте вспомним структуру http-пакетов:
- Стартовая строка — определяет тип сообщения;
- Заголовки — характеризуют тело сообщения, параметры передачи и прочие сведения;
- Тело сообщения — непосредственно данные сообщения.
Т.е. говоря headers already sent программа ругает нас, за то, что мы уже где-то начали формировать тело сообщения (3-ю часть http-пакета), но снова хотим отправить заголовки (2-ую часть).
Приведу пару примеров: лёгкий и адский – с точки зрения возможности заметить ошибку.
Пример 1 – лёгкий.
Будет выведена ошибка:
Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent
Мы не имели права вызывать функцию session_start(), после использования оператора echo. Такую ошибку исправить несложно – уберите отладочное echo.
Пример 2 – жуткий.
Представим, что у нас есть абстрактный файл модели model.php, который мы подключаем на нужную нам страничку a.php.
Но неожиданно денвер снова говорит:
Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent
Как? Почему? Ведь мы ещё не начинали формирования тела сообщения! И вот здесь, прежде чем удастся найти ошибку, можно расколотить компьютер или удалить локальный сервер. А всё приключилось потому, что мы нарушили золотое правило – никогда не закрывайте блок php, если в конкретном файле после него не идёт html.
Давайте взглянем на файл модели:
И оказывается, что мы всего-то навсего случайно поставили пробел после закрывающего ?>… Ненаходимая ошибка, этот пробел невозможно было и представить себе. Как же с этим бороться? А очень просто – не пишите закрывающее ?> в файлах с чистым php-кодом, и всё будет в порядке.
Также важно понимать, что речь идёт не только о конкретной функции session_start, но и обо всех остальных, которые выполняют отправку заголовков, например: setcookie, header итд.
- Не забывайте о том, что нельзя отправлять заголовки после того, как началось формирование тела сообщения
- Не пишите закрывающее ?> в файлах с чистым php
И об ошибке headers already sent Вы забудете!
Если скрипты WebAsyst установлены на вашем сервере или сервере хостинг-провайдера, в случае возникновения неполадки на сайте или в аккаунте WebAsyst может появиться сообщение следующего вида:
Такое сообщение означает, что в файле, путь к которому указан в скобках (/path/to/file.php), произошла преждевременная передача данных для передачи браузеру, в результате чего в файле, имя которого приведено в конце сообщения (/path/to/file.php), нарушилась работа функции, упомянутой после слова «Warning» — в данном примере session_start.
Преждевременная передача данных браузеру может быть вызвана несколькими причинами:
-
Неправильное изменение исходного кода или повреждение файла (в том числе вредоносным ПО — вирусами и т. п.). В этом случае необходимо восстановить оригинальное состояние файла. Для восстановления всех файлов выполните обновление с помощью WebAsyst Installer.
Совет: проблема может быть вызвана наличием в начале модифицированного PHP-файла служебного символа BOM (byte order mark), автоматически добавленного текстовым редактором, с помощью которого вносились изменения в исходный код скриптов. Чтобы удалить этот символ и устранить ошибку, откройте и снова сохраните файл, путь к которому указан в скобках в сообщении об ошибке — при этом используйте редактор кода, в котором отключена поддержка BOM.
Изначально когда проектировал сайт, работал с сессиями только на одной странице, где объявлял session_start(); Потом понадобилось распространить эту функцию на весь сайт. Для этого я разместил session_start() в файл config.php , который в свою очередь подключается к каждому файлу php сайта. Вот тут-то и возникли проблемы.
Структура сайта такова (заголовочные файлы):
Эти файлы подключаются к каждой странице сайта. А страницы разбиты по категориям в которых нет ошибки сессии: