Как исправить ошибку "Headers already sent" в PHP
Причина ошибки
Ошибка "Headers already sent" возникает, когда PHP-скрипт пытается отправить HTTP-заголовок (с помощью header(), setcookie(), session_start() и т.д.) после того, как тело ответа уже начало отправляться. В PHP заголовки должны отправляться до любого вывода — будь то echo, print, HTML-код или даже пустая строка перед <?php.
В вашем коде проблема в строке echo "Успешный вход!";. Этот вывод отправляется в браузер немедленно. После этого вызов header() уже невозможен, потому что заголовки были отправлены вместе с первым байтом вывода.
Решение 1: Убрать echo перед header()
Самый простой способ — не выводить ничего до вызова header(). Если вам нужно сообщить пользователю об успехе, сделайте это после редиректа на целевой странице.
<?php
session_start();
if ($_POST['login'] == 'admin' && $_POST['pass'] == '123') {
// Никакого echo! Просто редирект
header('Location: /dashboard.php');
exit;
}
?>
<html>
<head><title>Авторизация</title></head>
<body>
<form method="post">
<input type="text" name="login">
<input type="password" name="pass">
<button type="submit">Войти</button>
</form>
</body>
</html>
Решение 2: Использовать буферизацию вывода
Если вам обязательно нужно вывести что-то до редиректа (например, для отладки), включите буферизацию вывода с помощью ob_start() в начале скрипта. Тогда весь вывод будет накапливаться в буфере и не отправляться в браузер, пока вы не вызовете ob_end_flush().
<?php
ob_start(); // Включаем буферизацию
session_start();
if ($_POST['login'] == 'admin' && $_POST['pass'] == '123') {
echo "Успешный вход!";
header('Location: /dashboard.php');
ob_end_clean(); // Очищаем буфер и отправляем заголовки
exit;
}
ob_end_flush(); // Отправляем всё, что накопилось в буфере
?>
<html>
...
Решение 3: Проверить наличие BOM и пробелов
Частая причина — невидимые символы перед <?php. Убедитесь, что:
- В файле нет пробелов, табуляций или пустых строк перед открывающим тегом
<?php - Файл сохранён в кодировке UTF-8 без BOM (Byte Order Mark). BOM — это невидимые символы в начале файла, которые воспринимаются как вывод
- После закрывающего тега
?>нет лишних пробелов или переводов строки (лучше вообще не использовать закрывающий тег в конце файла)
<?php
// Правильно: нет пробелов перед <?php
// И нет закрывающего тега ?> в конце файла
session_start();
// ... ваш код
// Файл заканчивается без ?>
Дополнительные советы
- Всегда вызывайте
exitилиdieпослеheader('Location: ...'), чтобы скрипт не продолжал выполнение - Используйте функцию
headers_sent()для проверки, были ли уже отправлены заголовки:if (!headers_sent()) { header(...); } - В production-среде включите
output_bufferingв php.ini (обычно включено по умолчанию)
Альтернативный подход: разделение логики и представления
Вместо того чтобы бороться с ошибкой, лучше изменить архитектуру кода. Разделите логику обработки формы и отображение HTML. Это не только решит проблему с заголовками, но и сделает код чище и удобнее для поддержки.
Создайте два файла:
login.php — только форма:
<html>
<body>
<form method="post" action="auth.php">
<input type="text" name="login">
<input type="password" name="pass">
<button type="submit">Войти</button>
</form>
</body>
</html>
auth.php — только логика:
<?php
session_start();
if ($_POST['login'] == 'admin' && $_POST['pass'] == '123') {
$_SESSION['user'] = 'admin';
header('Location: /dashboard.php');
exit;
}
// Если данные неверные — редирект обратно с сообщением об ошибке
header('Location: /login.php?error=1');
exit;
Этот подход полностью исключает возможность вывода до заголовков, так как файл auth.php не содержит никакого HTML. Кроме того, он соответствует принципу единой ответственности (Single Responsibility Principle) и упрощает тестирование.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги