Как сделать редирект в WordPress с помощью PHP: полное руководство

Что такое редирект и зачем он нужен в WordPress

Редирект — это механизм автоматического перенаправления пользователя и поисковых роботов с одного URL-адреса на другой. В контексте WordPress редиректы критически важны для поддержания целостности сайта и пользовательского опыта при изменении структуры URL (например, смена постоянных ссылок), удалении контента или переносе страниц. Правильно настроенные редиректы помогают сохранить SEO-позиции, передавая «вес» старых страниц новым, и предотвращают попадание пользователей на несуществующие страницы (ошибки 404).

Когда использовать PHP для редиректов (в отличие от плагинов)

Хотя существует множество плагинов для управления редиректами (например, Redirection, Rank Math, Yoast SEO Premium), использование PHP напрямую оправдано в следующих случаях:

  • Производительность: Для простых или единичных редиректов кастомный PHP-код может быть более легковесным, чем установка и активация полноценного плагина.
  • Сложная логика: Если редирект должен срабатывать при выполнении специфических условий, недоступных в настройках плагинов (например, на основе роли пользователя, данных из стороннего API, времени суток), PHP предоставляет необходимую гибкость.
  • Интеграция: Редиректы могут быть частью более крупной кастомной функциональности, реализованной в теме или плагине.
  • Минимизация зависимостей: В некоторых проектах стремятся минимизировать количество установленных плагинов для упрощения обслуживания и повышения безопасности.

Предварительные требования: доступ к файлам WordPress и базовое понимание PHP

Для реализации редиректов с помощью PHP вам потребуется:

  • Доступ к файловой системе вашего сайта WordPress (через FTP, SFTP, SSH или файловый менеджер хостинга).
  • Возможность редактировать файлы темы (предпочтительно дочерней) или создавать собственные плагины.
  • Понимание основ PHP: синтаксис, функции, переменные, условные операторы.
  • Знание системы хуков WordPress (actions и filters) для интеграции вашего кода в нужный момент жизненного цикла запроса.

Основные методы редиректа с помощью PHP

Использование функции wp_redirect() WordPress

Функция wp_redirect(string $location, int $status = 302): bool является стандартным и рекомендуемым способом выполнения редиректов в WordPress. Она не только отправляет HTTP-заголовок Location, но и корректно завершает выполнение скрипта с помощью wp_die(), если редирект удался.

  • $location: Целевой URL для перенаправления.
  • $status: HTTP-код состояния редиректа (по умолчанию 302 — временный редирект). Используйте 301 для постоянных редиректов.

Преимущество wp_redirect() в том, что она интегрирована с WordPress и может быть легко использована внутри хуков.

<?php
/**
 * Перенаправляет со старой страницы на новую.
 *
 * @param string $location URL для перенаправления.
 * @param int    $status   HTTP статус код редиректа.
 * @return void
 */
function custom_redirect_old_page(string $location, int $status = 302): void {
    // Выполняем редирект и завершаем выполнение скрипта
    if (wp_redirect($location, $status)) {
        exit;
    }
}

// Пример использования внутри хука template_redirect
add_action('template_redirect', function() {
    // Проверяем, находимся ли мы на конкретной старой странице (например, по ID)
    if (is_page(123)) { // Замените 123 на ID вашей старой страницы
        $new_url = home_url('/new-page-slug/');
        custom_redirect_old_page($new_url, 301); // Постоянный редирект
    }
});

Редирект с помощью функции header() PHP: преимущества и недостатки

Нативная функция PHP header(string $header, bool $replace = true, ?int $response_code = null) позволяет отправлять необработанные HTTP-заголовки. Для редиректа используется заголовок Location.

<?php
/**
 * Отправляет заголовок Location для редиректа.
 *
 * Важно: Эта функция должна вызываться до любого вывода в браузер.
 *
 * @param string $location      URL для перенаправления.
 * @param int    $status_code   HTTP статус код редиректа (301 или 302).
 * @param bool   $exit_script   Завершить ли выполнение скрипта после отправки заголовка.
 * @return void
 */
function native_php_redirect(string $location, int $status_code = 302, bool $exit_script = true): void {
    // Убедимся, что код статуса валиден для редиректа
    if ($status_code !== 301 && $status_code !== 302 && $status_code !== 307) {
        $status_code = 302;
    }

    // Устанавливаем код ответа
    http_response_code($status_code);

    // Отправляем заголовок Location
    header("Location: " . $location, true, $status_code);

    // Важно завершить выполнение скрипта
    if ($exit_script) {
        exit;
    }
}

// Пример использования (менее предпочтителен, чем wp_redirect)
// Можно использовать на очень ранних хуках, до инициализации WP
if (isset($_GET['legacy_param']) && $_GET['legacy_param'] === 'redirect_me') {
    native_php_redirect('https://new-domain.com/target', 301);
}

Преимущества:

  • Может быть вызван очень рано, до полной загрузки WordPress.

Недостатки:

  • Ошибка «Headers already sent»: Самая частая проблема. Если перед вызовом header() произошел какой-либо вывод (HTML, пробелы, ошибки PHP), функция не сработает и вызовет ошибку.
  • Требует ручного вызова exit; или die; для прекращения выполнения скрипта после редиректа.
  • Менее интегрирован с WordPress, чем wp_redirect().

Выбор правильного кода состояния HTTP для редиректа (301, 302, 307)

Выбор корректного HTTP-статуса имеет решающее значение, особенно для SEO:

  • 301 Moved Permanently: Используется, когда ресурс навсегда перемещен на новый URL. Поисковые системы передают основной «вес» (link juice) старого URL новому. Это наиболее частый выбор при изменении структуры сайта или удалении/объединении страниц.
  • 302 Found (или HTTP/1.0 Moved Temporarily): Используется, когда ресурс временно доступен по другому URL. Поисковые системы обычно не передают «вес» ссылки и продолжают индексировать исходный URL. Применяется для A/B тестирования, редиректов на основе геолокации или временных акций.
  • 307 Temporary Redirect: Похож на 302, но гарантирует, что HTTP-метод запроса (GET, POST и т.д.) не будет изменен при перенаправлении. Используйте 307 вместо 302, если важно сохранить метод запроса (например, при редиректе POST-запроса).

Ключевое правило: Используйте 301 для постоянных изменений, 302 или 307 для временных.

Реализация редиректов на практике: пошаговые примеры

Редирект с одной страницы на другую (фиксированный URL)

Это самый распространенный сценарий. Используем хук template_redirect, который срабатывает перед загрузкой шаблона страницы.

<?php
add_action('template_redirect', function(): void {
    // Проверяем, что это не админ-панель и что мы на нужной странице
    // Можно проверять по ID, слагу (post_name) или пути запроса
    if (!is_admin() && is_page('old-slug')) { // Замените 'old-slug' на слаг вашей старой страницы
        $new_url = home_url('/new-page-or-post-slug/'); // Укажите URL новой страницы
        if (wp_redirect($new_url, 301)) {
            exit;
        }
    }

    // Пример редиректа по ID поста
    if (!is_admin() && is_single(45)) { // Замените 45 на ID старого поста
         $new_post_url = get_permalink(101); // Получаем URL нового поста по ID
         if ($new_post_url && wp_redirect($new_post_url, 301)) {
            exit;
         }
    }
});

Редирект на основе условий (например, роли пользователя)

Можно перенаправлять пользователей в зависимости от их роли или прав.

<?php
add_action('template_redirect', function(): void {
    // Перенаправляем подписчиков (subscribers) с определенной страницы
    if (is_page('premium-content') && current_user_can('subscriber')) {
        $dashboard_url = home_url('/dashboard/');
        if (wp_redirect($dashboard_url, 302)) { // Временный редирект
            exit;
        }
    }

    // Перенаправляем НЕавторизованных пользователей со страницы профиля
    if (is_page('my-profile') && !is_user_logged_in()) {
        $login_url = wp_login_url(get_permalink()); // Редирект на логин с возвратом на страницу профиля
        if (wp_redirect($login_url, 302)) {
            exit;
        }
    }
});

Редирект после авторизации пользователя

Используйте фильтр login_redirect для управления тем, куда пользователь попадает после успешного входа.

<?php
/**
 * Изменяет URL перенаправления после входа пользователя.
 *
 * @param string  $redirect_to           URL для перенаправления по умолчанию.
 * @param string  $requested_redirect_to URL, запрошенный пользователем (если есть).
 * @param WP_User $user                  Объект пользователя, который вошел.
 * @return string Новый URL для перенаправления.
 */
function custom_login_redirect(string $redirect_to, string $requested_redirect_to, WP_User $user): string {
    // Если у пользователя есть определенные права (например, 'edit_posts')
    if (isset($user->roles) && is_array($user->roles)) {
        // Редирект администраторов и редакторов в админ-панель
        if (in_array('administrator', $user->roles) || in_array('editor', $user->roles)) {
            return admin_url(); // URL админ-панели WordPress
        }
        // Редирект подписчиков на их страницу профиля
        elseif (in_array('subscriber', $user->roles)) {
            return home_url('/user-profile/');
        }
    }

    // Для всех остальных - стандартное поведение
    // Если был запрошен конкретный URL ($requested_redirect_to), используем его
    if (!empty($requested_redirect_to)) {
         return $requested_redirect_to;
    }

    // Иначе возвращаем URL по умолчанию (часто это админ-панель или главная)
    return $redirect_to;
}
add_filter('login_redirect', 'custom_login_redirect', 10, 3);
Реклама

Редирект 404 ошибок на главную страницу или указанный URL

Хотя редирект всех 404 на главную не всегда является лучшей практикой с точки зрения SEO и UX (лучше показывать информативную страницу 404), это можно реализовать.

<?php
add_action('template_redirect', function(): void {
    // Проверяем, является ли текущий запрос страницей 404
    if (is_404()) {
        $home_url = home_url('/');
        // Выполняем временный редирект (302), чтобы не индексировать главную как замену всех 404
        if (wp_redirect($home_url, 302)) {
            exit;
        }
        // Альтернативно: редирект на специальную страницу поиска или карту сайта
        // $search_page_url = home_url('/search-results-custom/');
        // if (wp_redirect($search_page_url, 302)) { exit; }
    }
});

Важно: Используйте 302 редирект для 404, чтобы не создавать ложное впечатление у поисковых систем, что главная страница является постоянной заменой всех удаленных URL.

Размещение PHP-кода для редиректов: functions.php и другие варианты

Редактирование functions.php: плюсы и минусы, создание дочерней темы

Файл functions.php активной темы — самое очевидное место для добавления PHP-кода.

  • Плюсы: Простота добавления кода.
  • Минусы:
    • Потеря изменений при обновлении темы: Если вы не используете дочернюю тему, все изменения в functions.php будут перезаписаны при обновлении родительской темы.
    • Беспорядок: Файл может быстро стать громоздким и трудным для навигации при добавлении множества разнородных функций.
    • Привязка к теме: Функциональность редиректов будет работать только при активной данной теме.

Решение: Всегда используйте дочернюю тему для внесения изменений в functions.php. Это стандартная практика WordPress, позволяющая безопасно модифицировать и расширять функциональность родительской темы.

Использование пользовательских плагинов для организации кода

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

  • Плюсы:
    • Независимость от темы: Код работает независимо от активной темы.
    • Организация: Позволяет структурировать код, разделяя разную функциональность по разным файлам или плагинам.
    • Управляемость: Плагин можно легко активировать/деактивировать.
    • Переносимость: Легко перенести на другой сайт.
  • Минусы: Требует создания базовой структуры плагина (заголовочный комментарий).

Примеры кода для размещения в functions.php и плагине

Пример для functions.php (дочерней темы):

<?php
// В functions.php вашей дочерней темы

/**
 * Добавляет правила редиректа.
 */
function my_custom_redirects(): void {
    // Пример 1: Редирект старого слага
    if (is_page('old-about-us')) {
        $url = home_url('/about/');
        if (wp_redirect($url, 301)) { exit; }
    }

    // Пример 2: Редирект неавторизованных с приватной страницы
    if (is_page('members-only') && !is_user_logged_in()) {
        $url = wp_login_url(get_permalink());
        if (wp_redirect($url, 302)) { exit; }
    }
}
add_action('template_redirect', 'my_custom_redirects');

/**
 * Редирект после логина для авторов.
 */
function author_login_redirect(string $redirect_to, string $requested_redirect_to, WP_User $user): string {
    if (isset($user->roles) && is_array($user->roles) && in_array('author', $user->roles)) {
        return home_url('/author-dashboard/');
    }
    return $redirect_to;
}
add_filter('login_redirect', 'author_login_redirect', 10, 3);

Пример для пользовательского плагина:

Создайте файл my-custom-redirects.php в папке wp-content/plugins/my-custom-redirects/.

<?php
/**
 * Plugin Name:       My Custom Redirects
 * Plugin URI:        https://example.com/plugins/my-custom-redirects/
 * Description:       Handles custom PHP redirects for the site.
 * Version:           1.0.0
 * Author:            Your Name
 * Author URI:        https://example.com/
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       my-custom-redirects
 * Domain Path:       /languages
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

class My_Custom_Redirect_Plugin {

    public function __construct() {
        add_action('template_redirect', [$this, 'handle_page_redirects']);
        add_filter('login_redirect', [$this, 'handle_login_redirect'], 10, 3);
    }

    /**
     * Handles page-based redirects.
     */
    public function handle_page_redirects(): void {
        if (is_admin()) {
            return;
        }

        // Редирект /old-service -> /services/new-service
        if (is_page('old-service')) {
            $url = home_url('/services/new-service/');
            if (wp_redirect($url, 301)) { exit; }
        }

        // Добавьте другие редиректы здесь...
    }

    /**
     * Handles redirects after user login.
     *
     * @param string  $redirect_to           Default redirect URL.
     * @param string  $requested_redirect_to Requested redirect URL.
     * @param WP_User $user                  Logged-in user object.
     * @return string New redirect URL.
     */
    public function handle_login_redirect(string $redirect_to, string $requested_redirect_to, WP_User $user): string {
        if (isset($user->roles) && is_array($user->roles) && in_array('customer', $user->roles)) {
             // Если пустой $requested_redirect_to, отправляем на страницу аккаунта
             return empty($requested_redirect_to) ? home_url('/my-account/') : $requested_redirect_to;
        }
        return $redirect_to;
    }
}

// Initialize the plugin
new My_Custom_Redirect_Plugin();

Активируйте этот плагин через админ-панель WordPress.

Решение проблем и отладка редиректов

Главная проблема — «Warning: Cannot modify header information — headers already sent by (output started at /path/to/file.php:line)». Она возникает, если любой вывод (даже пробел или BOM-метка UTF-8) отправляется в браузер до вызова header() или wp_redirect() (который внутри использует header()).

  • Решение: Убедитесь, что ваш код редиректа выполняется на достаточно раннем хуке (init, template_redirect) до начала вывода HTML-разметки темой или другими плагинами.
  • Проверка: Проверьте файлы (wp-config.php, functions.php, файлы плагинов), которые подключаются до вашего кода редиректа, на наличие пустых строк или пробелов вне тегов <?php ... ?>.
  • Предпочтение: Используйте wp_redirect(), так как она спроектирована для работы в среде WordPress и вызывается на этапах, когда отправка заголовков еще возможна.

Проверка правильности работы редиректа с помощью инструментов разработчика

  1. Откройте браузер в режиме инкогнито (чтобы избежать влияния кеша).
  2. Откройте Инструменты разработчика (обычно F12).
  3. Перейдите на вкладку «Сеть» (Network).
  4. Установите галочку «Сохранять журнал» (Preserve log) или аналогичную.
  5. Введите старый URL, который должен редиректить, в адресную строку и нажмите Enter.
  6. В списке запросов найдите первый запрос к вашему старому URL. Его статус должен быть 301, 302 или 307.
  7. Проверьте значение заголовка ответа Location — он должен содержать правильный новый URL.

Также можно использовать онлайн-сервисы проверки редиректов (например, Redirect Checker).

Решение проблем с кешированием редиректов

  • Кеш браузера: Редиректы, особенно 301, агрессивно кешируются браузерами. Очистите кеш браузера или используйте режим инкогнито для проверки.
  • Кеш сервера/WordPress: Если вы используете плагины кеширования (W3 Total Cache, WP Super Cache, LiteSpeed Cache и т.д.) или серверное кеширование (Varnish, Nginx cache), очистите кеш WordPress и/или серверный кеш после внесения изменений в код редиректов.
  • CDN Кеш: Если используется CDN, кеш CDN также может потребовать очистки.

Альтернативы: когда стоит использовать плагины для редиректов

Хотя PHP дает полный контроль, использование специализированных плагинов предпочтительнее, когда:

  • Требуется управлять большим количеством редиректов.
  • Необходимо использовать регулярные выражения для создания сложных правил перенаправления.
  • Нужен пользовательский интерфейс для добавления, редактирования и мониторинга редиректов (включая отслеживание 404 ошибок).
  • Требуется ведение логов срабатывания редиректов.
  • Предпочитаете решение «из коробки» без необходимости писать и отлаживать код.

Популярные плагины: Redirection, Rank Math SEO, Yoast SEO Premium.

Выбор между PHP и плагином зависит от конкретной задачи, масштаба проекта и вашего уровня комфорта при работе с кодом.


Добавить комментарий