Редирект в PHP: 5 фатальных ошибок и как их избежать

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему редирект в PHP — это не просто header('Location:')

Каждый, кто хоть раз писал на PHP, сталкивался с задачей перенаправления пользователя на другую страницу. Казалось бы, что может быть проще? Одна строчка header('Location: /new-page'); — и готово. Но на практике этот простой механизм превращается в головную боль для тысяч разработчиков. Не зря вопрос «How do I make a redirect in PHP?» на Stack Overflow собрал миллионы просмотров.

Проблема в том, что редирект в PHP — это не просто вызов функции, а целый процесс, который легко сломать. Вы когда-нибудь видели ошибку «Cannot modify header information»? Или замечали, что редирект работает, но страница всё равно загружается? Или, что ещё хуже, сталкивались с тем, что редирект вообще не срабатывает, а пользователь видит пустую страницу?

В этой статье мы разберём 5 самых частых ошибок при создании редиректа в PHP, научимся их исправлять и узнаем, как сделать перенаправление безопасным и предсказуемым. Поехали!

Ошибка №1: Редирект после вывода контента (Header already sent)

Суть проблемы

Самая распространённая ошибка новичков — попытка отправить HTTP-заголовок Location после того, как в браузер уже ушёл HTML-код или даже один пробел. PHP выдаёт фатальную ошибку: «Cannot modify header information - headers already sent».

Почему это происходит?

HTTP-протокол устроен так, что заголовки должны отправляться строго до тела ответа. Как только PHP выводит что-то на экран (через echo, print, даже пустую строку перед <?php), заголовки уже зафиксированы. Изменить их нельзя.

Пример ошибки

<?php
echo "Привет!";
header('Location: /dashboard.php'); // ОШИБКА: заголовки уже отправлены
?>

Как исправить

  • Правило №1: вызывайте header() до любого вывода, включая пробелы и HTML
  • Правило №2: убедитесь, что в вашем PHP-файле нет пробелов или пустых строк до <?php или после ?>
  • Правило №3: используйте буферизацию вывода, если без раннего вывода не обойтись
<?php
// Правильно: редирект до любого вывода
header('Location: /dashboard.php');
exit;
?>

Буферизация вывода (продвинутый метод):

<?php
ob_start(); // Включаем буферизацию
echo "Временный контент";
header('Location: /dashboard.php');
ob_end_flush(); // Отправляем всё разом
exit;
?>

Ошибка №2: Забытый exit (или die) после редиректа

Суть проблемы

Вызов header('Location: ...') не останавливает выполнение скрипта автоматически. PHP продолжает обрабатывать код дальше, а браузер, получив заголовок, начинает загружать новую страницу. Но что, если после редиректа идёт ресурсоёмкий код или, что ещё опаснее, код, изменяющий данные в базе?

Пример ошибки

<?php
header('Location: /success.php');
// Пользователь уже перенаправлен, но PHP продолжает работу!
update_user_balance($userId, -1000); // ОПАСНО: списание средств
send_email_to_admin("Пользователь совершил покупку");
?>

Как исправить

Всегда используйте exit (или die) сразу после вызова header(). Это гарантирует, что скрипт завершится и никакой лишний код не выполнится.

<?php
header('Location: /success.php');
exit; // Полная остановка скрипта
// Код ниже уже не выполнится
update_user_balance($userId, -1000);
?>

Ошибка №3: Неправильный URL (относительные vs абсолютные)

Суть проблемы

Стандарт HTTP требует, чтобы значение заголовка Location содержало абсолютный URL (с протоколом и доменом). Хотя многие современные браузеры понимают и относительные пути, полагаться на это — плохая практика. На старых браузерах или в некоторых прокси-серверах относительный редирект может не сработать.

Пример ошибки

<?php
header('Location: /dashboard'); // Относительный путь — может не сработать
exit;
?>

Как исправить

Формируйте полный URL. Лучший способ — использовать суперглобальный массив $_SERVER для динамического построения адреса.

<?php
// Простой вариант
header('Location: https://' . $_SERVER['HTTP_HOST'] . '/dashboard');
exit;

// Универсальный вариант с проверкой HTTPS
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
header('Location: ' . $protocol . '://' . $_SERVER['HTTP_HOST'] . '/dashboard');
exit;
?>

Ошибка №4: Игнорирование кода состояния (301, 302, 303)

Суть проблемы

По умолчанию PHP отправляет редирект с кодом 302 (Found) — временное перенаправление. Но в реальных проектах часто требуется явно указать тип редиректа: постоянный (301), временный (302) или редирект с изменением метода запроса (303). Ошибка в коде может привести к проблемам с SEO или некорректной работе API.

Пример ошибки

<?php
// По умолчанию 302 — временный редирект
header('Location: /new-page');
exit;
?>

Как исправить

Используйте второй параметр функции header() для замены предыдущего заголовка и третий — для указания кода состояния.

<?php
// Постоянный редирект (301) — для SEO, когда страница навсегда изменила адрес
header('Location: /new-page', true, 301);
exit;

// Редирект после POST-запроса (303) — чтобы избежать повторной отправки формы
header('Location: /success', true, 303);
exit;

// Временный редирект (302) — явное указание
header('Location: /maintenance', true, 302);
exit;
?>

Когда какой код использовать?

  • 301 Moved Permanently — стра

Блоги

Рекомендаций по книгам