Глиф Учебники

Как сделать редирект в PHP

Справочник · PHP · 2 минуты чтения

PHP
<?php
header('Location: /catalog.php');
exit;

header('Location: …') отправляет браузеру заголовок «иди по этому адресу», и браузер сразу открывает новую страницу. Адрес может быть путём на своём сайте (/catalog.php) или полным адресом (https://example.com/page).

exit после header обязателен. Без него PHP выполнит файл до конца, и всё, что идёт ниже, уйдёт браузеру. Для закрытой страницы это значит, что её содержимое получит любой — просто не увидит в браузере из-за перенаправления, а программа для скачивания страниц увидит.

Какой код ответа выбрать

По умолчанию Location отправляется с кодом 302 — «временно перемещено». Другой код задают третьим аргументом:

PHP
<?php
header('Location: https://example.com/new-page', true, 301);
exit;
КодКогда
301страница переехала насовсем; поисковики переносят адрес в выдаче на новый
302временное перенаправление: на вход, на выбранный язык
303после обработки формы POST — на страницу результата
307, 308как 302 и 301, но браузер повторит тот же метод (POST останется POST)

Браузер запоминает 301 надолго. Проверяйте перенаправление сначала с 302 и меняйте на 301, когда всё работает: ошибочный постоянный редирект у посетителей потом трудно отменить.

Редирект после формы

После успешной отправки формы перенаправляйте посетителя, чтобы обновление страницы (F5) не отправило данные повторно:

PHP
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // проверка и сохранение данных…
    header('Location: /thanks.php', true, 303);
    exit;
}

Полный пример — в справке Как отправить форму на ту же страницу.

Редирект не работает

Адрес от посетителя

Не перенаправляйте на адрес, который пришёл из формы или ссылки, без проверки: header('Location: ' . $_GET['back']). Злоумышленник пришлёт ссылку на ваш сайт, которая уведёт посетителя на поддельную страницу входа, — это «открытый редирект».

Безопасно принимать только путь своего сайта:

PHP
<?php
$back = $_GET['back'] ?? '/';
$isLocal = is_string($back)
    && str_starts_with($back, '/')
    && !str_starts_with($back, '//')
    && !str_contains($back, '\\');
if (!$isLocal) {
    $back = '/';
}
header('Location: ' . $back);
exit;

Путь должен начинаться с одной косой черты и не содержать обратной: адреса //example.com и /\example.com браузер понял бы как переход на другой сайт. Проверка is_string нужна потому, что вместо строки в адресе можно передать массив (?back[]=1).

Перенаправить весь сайт

Перевод всего сайта с http на https или с www на адрес без www удобнее делать в настройках веб-сервера или в панели хостинга, а не в каждом PHP-файле: такое правило срабатывает до PHP и для всех файлов сразу.