Все способы редиректа в PHP: от простого к сложному
Редирект в PHP: основные методы и их реализация
Основной способ: функция header()
Наиболее эффективным решением для перенаправления является использование функции header() с параметром Location. Этот метод отправляет HTTP-заголовок, который указывает браузеру перейти на новый URL. После вызова header() обязательно вызывать exit или die, чтобы скрипт не продолжал выполнение.
header('Location: https://example.com/new-page');
exit;
Код статуса по умолчанию - 302 (временный редирект). Для постоянного редиректа используется код 301:
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://example.com/permanent');
exit;
Типичная ошибка: «Headers already sent»
Эта ошибка возникает, если до вызова header() был выведен любой текст (включая пробелы или HTML). Решение - использовать буферизацию вывода (ob_start()) в начале скрипта либо перенести логику редиректа до любого вывода.
ob_start();
// ... код, который может выводить данные
header('Location: https://example.com');
ob_end_flush();
exit;
Цели использования: перенаправление после обработки формы, защита от повторной отправки (PRG-паттерн), смена версии протокола, редиректы при авторизации.
Как сделать редирект через HTML meta refresh?
Этот вариант используется, когда невозможно повлиять на HTTP-заголовки (например, на статической странице). Редирект выполняется на стороне браузера с задержкой.
<meta http-equiv="refresh" content="3;url=https://example.com">
Атрибут content: число - задержка в секундах, затем точка с запятой и URL. Цель - дать пользователю увидеть сообщение перед переходом. Проблема: не работает, если у пользователя отключена поддержка meta refresh; плохо для SEO.
Ошибка: некорректный синтаксис
Пропуск точки с запятой или кавычек приводит к тому, что редирект не срабатывает или переходит на неправильный адрес.
Как выполнить редирект средствами JavaScript?
JavaScript-редирект применяется, когда нужно перенаправить пользователя после выполнения каких-либо действий на клиенте (например, после нажатия кнопки).
window.location.href = 'https://example.com';
// или
window.location.replace('https://example.com');
Разница: href сохраняет историю, replace замещает текущую запись. Цель - гибкое управление навигацией. Проблема: не работает при отключённом JavaScript, может быть медленнее HTTP-редиректа.
Блокировка браузером
Некоторые браузеры могут блокировать перенаправление, если оно происходит без действия пользователя (например, в iframe).
Как настроить редирект через .htaccess (Apache)?
Серверный редирект с помощью модуля mod_rewrite эффективен для постоянных перенаправлений и не требует написания PHP-кода на каждой странице.
RewriteEngine On
RewriteRule ^old-page$ /new-page [R=301,L]
Цель: изменить структуру URL, объединить сайты, перенаправить весь трафик с HTTP на HTTPS. Проблема: требует доступа к конфигурации сервера, ошибки в синтаксисе могут привести к 500 ошибке.
Бесконечный цикл редиректов
Неправильное правило может вызвать зацикливание. Решение - использовать флаги L (last) и проверять условия.
Как реализовать редирект с помощью PHP-функции с выбором кода статуса?
Для разных сценариев (временный, постоянный, другой метод) используются разные HTTP-коды. Примеры:
header('Location: /temporary', true, 302); // временный
header('Location: /moved', true, 301); // постоянный
header('Location: /see-other', true, 303); // после POST
Цель - соответствие семантике HTTP. Проблема: неправильный код может сбить SEO или кэширование.
Расширенные примеры редиректов в PHP
Пример 1. Редирект с сохранением GET-параметров
Иногда нужно перенаправить пользователя, сохранив все переданные GET-параметры. Для этого собираем текущий массив $_GET и формируем новый URL.
$get = $_GET;
$get['ref'] = 'redirect';
$query = http_build_query($get);
header('Location: /new?' . $query);
exit;
Результат: если исходный URL был /old?page=1&sort=asc, то редирект приведёт на /new?page=1&sort=asc&ref=redirect.
Пример 2. Редирект после обработки POST-формы (PRG)
Для предотвращения повторной отправки формы при обновлении страницы используется паттерн Post/Redirect/Get. После обработки POST-данных редиректим на GET-страницу.
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// ... обработка формы
$_SESSION['message'] = 'Данные сохранены';
header('Location: /success');
exit;
}
Результат: при обновлении страницы браузер повторяет только GET-запрос, форма не отправляется повторно.
Пример 3. Условный редирект на мобильную версию
Определяем User-Agent и перенаправляем на мобильный поддомен.
$mobile_agents = array('Mobile', 'Android', 'iPhone', 'iPad');
$is_mobile = false;
foreach ($mobile_agents as $agent) {
if (strpos($_SERVER['HTTP_USER_AGENT'], $agent) !== false) {
$is_mobile = true;
break;
}
}
if ($is_mobile && !strpos($_SERVER['HTTP_HOST'], 'm.')) {
header('Location: https://m.example.com' . $_SERVER['REQUEST_URI']);
exit;
}
Результат: пользователь с мобильного устройства попадает на m.example.com, остальные - на основной сайт. Проблема: User-Agent легко подделывается, лучше использовать серверное определение.
Пример 4. Редирект с задержкой и сообщением
Если нужно показать пользователю уведомление «Вы будете перенаправлены через 5 секунд», используется комбинация PHP и HTML.
header('Refresh: 5; URL=https://example.com');
?>
<!DOCTYPE html>
<html>
<head><title>Перенаправление...</title></head>
<body>
<p>Через 5 секунд вы перейдёте на <a href="https://example.com">example.com</a></p>
</body>
</html>
Результат: браузер сначала отображает страницу с сообщением, затем через 5 секунд выполняет редирект.
Пример 5. Редирект на основе IP-адреса (для геотаргетинга)
Можно перенаправить пользователей из определённой страны на локальную версию сайта.
$ip = $_SERVER['REMOTE_ADDR'];
// гипотетическая функция определения страны
$country = geoip_country_code_by_name($ip);
if ($country === 'RU') {
header('Location: https://ru.example.com');
} elseif ($country === 'DE') {
header('Location: https://de.example.com');
} else {
header('Location: https://en.example.com');
}
exit;
Результат: в зависимости от IP браузер получает соответствующий редирект. Проблема: неточность определения, необходимо расширение GeoIP.
Пример 6. Множественные редиректы и защита от бесконечного цикла
При цепочке редиректов важно ограничивать количество шагов.
function safe_redirect($url, $max_redirects = 5) {
static $count = 0;
if ($count >= $max_redirects) {
throw new Exception('Превышено количество редиректов');
}
$count++;
header('Location: ' . $url);
exit;
}
Результат: при превышении лимита выбрасывается исключение. Использование: safe_redirect('/some-path');
Пример 7. Логирование редиректов
Для отладки или аналитики записываем каждый редирект в файл.
function redirect_with_log($url, $code = 302) {
$log = date('Y-m-d H:i:s') . ' | ' . $_SERVER['REQUEST_URI'] . ' -> ' . $url . ' | ' . $code . PHP_EOL;
file_put_contents('/var/log/redirects.log', $log, FILE_APPEND);
header('Location: ' . $url, true, $code);
exit;
}
Результат: каждый редирект фиксируется в лог-файле с временем, источником и кодом.