Необыкновенный роутинг на WordPress

Необыкновенный роутинг на WordPress

Статьи

Привет! Данное видео я хотел бы посвятить роутингу во всеми нами любом WordPress. И я даже сделаю смелое предположение — скорее всего, такого вы ещё не видели.

Ниже — текстовый вариант того, что есть в видео =)

Итак, роутинг в WordPress… Какие мы знаем варианты? До определённого времени я знал только 2 нормальных способа и ещё один, но он специфический. Очень.

Самый первый, самый традиционный — это использование хука wp_ajax. Думаю, все его уже сотню или даже тысячу раз видели, не вижу смысла на нём сильно останавливаться.

Второй вариант — REST API. Был полноценно добавлен в ядро с версии 4.7. И мне эта концепция общения понравилась больше всего. Что говорить — стандартный (теперь уже) редактор Gutenberg использует для своей работы как раз REST. На нём предлагаю тоже не останавливаться, потому что и технология уже известная, да и у сам я отметился несколькими статьями и видео, посвящёнными этому вопросу.

Скажу только, что и у REST есть свои нюансы. Например, в обработчике запроса мы не можем получить авторизованного пользователя. Или же возможность возвращать ответ только в JSON.

Да, есть ещё специфический вариант… О нём расскажу, но ещё раз отмечу, что он… Ну такой… Суть его в том, что для создания структуры роутов используются записи WordPress и их возможность древовидной структуры. Стандартными страницами или кастомными типами мы выстраиваем свои ветки, где на каждый поинт есть свой шаблон страницы, в котором приходящий запрос будет уже обработан.

Данный вариант имеет и свои плюсы, но и минусы у него тоже есть. Главный — при создании нового экземпляра приложения всю структуру страниц нужно будет либо создавать вручную (но это уже совсем упоротый путь, не делайте так), либо предусмотреть механизм, который будет эту структуру хранить.

Однажды я предложил сделать такой вариант, но мой тимлид очень ёмко объяснил, что такой подход мы использовать не будем.

Но в этот момент началось моё путешествие в удивительный мир под названием «А как мы ещё можем организовать роутинг на WordPress?».

Что мне хотелось получить:

  • структура роутов задаётся в коде; в качестве референса мне очень понравился (и до сих пор нравится) подход, который используется в Laravel
  • можно возвращать json, а можно и html… Да и вообще не быть привязанным к какому-то конкретному формату, нужно больше рок-н-ролла!
  • не мучаться с определением авторизованного пользователя

В формате вечерних серфов по интернету время от времени я искал нечто мне подходящее, но так и не нашёл. Поэтому предупреждаю сразу — возможно, вы такой вариант уже где-то и у кого-то видели, но вот я нет.

А то мне под прошлой статьей накидали ссылок на схожий по концепции компонентный подход. Что могу сказать — у талантливых людей мысли совпадают =)

Итак, суть подхода такова — мы используем событие wp, на котором перехватываем запрос и перенаправляем его в нужное нам русло.

Событие wp нам нужно потому, что там есть очень интересный параметр — $wp->request — который нам поможет работать с текущим url-адресом. Плюс, у нас в этот момент уже будет в наличии авторизованный пользователь.

Как мы делаем перехват? Очень просто — нужно регулярное выражение, по которому мы будем проверять значение $wp->request. Если оно нам подходит — запускаем нужную функцию. Чтобы не мучаться каждый раз с регулярками, я написал специальный класс CustomRoute, который всю рутину забирает на себя.

Нам остаётся лишь написать немного кода.

add_action('wp', 'customRouter');
function customRouter()
{
    global $wp;
    switch (true) {

        case ($request = CustomRoute::parseRoute('magic-page/{value1}/{value2}', $wp->request)): {
            CustomRoute::responseHtml(otherHandler($request['value1'], $request['value2']));
        }

        case ($request = CustomRoute::parseRoute('any-action/{filter1}/{filter2}', $wp->request)): {
            CustomRoute::responseJson(anotherHandler($request['filter1'], $request['filter2']));
        }

        default: return null;
    }
}

Дополним пример функциями-обработчиками:

function otherHandler(string $filter1, string $filter2): string
{
    $user = wp_get_current_user();

    return(
        '<p>login: '. $user->user_login .'</p>' .
        '<p>filter1: '. $filter1 .'</p>' .
        '<p>filter2: '. $filter2 .'</p>'
    );
}


function anotherHandler(string $filter1, string $filter2): array
{
    if(!is_user_logged_in()) return accessDeniedJson();

    $user = wp_get_current_user();

    return [
        'user' => [
            'login' => $user->user_login,
            'nicename' => $user->user_nicename,
            'role' => current($user->roles)
        ],
        'filter1' => $filter1,
        'filter2' => $filter2
    ];
}


function accessDeniedJson(): array
{
    return [
        'code' => 401,
        'message' => 'access denied'
    ];
}

Не забудьте подключить файл core.php в functions.php.

И всё! Дальше нам останется в функции произвести нужные нам операции.

Код класса доступен по ссылке — можете посмотреть, попробовать и доработать под свои нужды.

А на этом у меня всё. Не забывайте, что код — это поэзия!

Анатолий Куликов

Анатолий Куликов

Автор блога, веб-разработчик
  • at sign
  • vk logo
Комментариев нет

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

Для отправки комментария вам необходимо авторизоваться.