WordPress & JS

WordPress & JS

Уроки

При разработке приложений на JavaScript, будь то чиcтый js или один из многочисленных фреймворков, рано или поздно возникает вопрос — как наладить общение с базой данных?

Варианты ответа вроде элементарны:

  • используем Node.js для разработки серверной части приложения (это ведь тоже JavaScript);
  • используем Python / Django для той же цели;
  • используем классический вариант — PHP.

Хорошо, когда вы работаете в команде и есть back-end разработчик, который все эти вопросы возьмёт на себя, вам же выдаст инструкцию — куда какие запросы посылать, чтобы получить данные из базы.

Но иногда приходится косплеить fullstack-разработчика. Данная статья как раз об этом.

Здесь мы не будем рассматривать очевидные и популярные варианты (Node.js и Python), а сделаем своё собственное API на PHP, и поможет нам в этом старый-добрый WordPress.

В этой статье мы в общем виде и кратко, но ёмко рассмотрим, как можно организовать этакий middle-end. Здесь мы не будем рассматривать подробно разработку на javascript, только в общем виде покажем части некоего абстрактного приложения.

Перед самым началом

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

Также рекомендую — если вдруг у вас ещё в арсенале не присутствует — классную программу Postman, с помощью которой очень удобно отлаживать работу API.

Подготовка

Для начала разберёмся, что за приложение мы будем создавать — это поможет нам разобраться, какую именно информацию мы будем запрашивать из базы данных через WordPress.

Допустим, мы решили сделать приложение, которое имеет следующий функционал:

  • Авторизует пользователя — просто проверим, есть ли такой пользователь вообще. Регистрацию / восстановление мы вынесенем за рамки статьи, ибо по прочтении её такое вы сможете сделать уже самостоятельно (пусть будет домашкой).
  • Выводит авторизованному пользователю записи из базы данных.

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

Итак, соответственно нам необходимо создать 2 энд-поинта, с помощью которых мы будем общаться со всей системой. Предлагаю их назвать кратко и лаконично — auth и post.

Забегая немного вперед, скажу что мы не будем пользоваться стандартными роутами WordPress для получения постов / записей, а сделаем все ручками.

Поехали!

Создаём роуты

Итак, мы договорились, что никаким образом не будем пользоваться стандартными средствами. Поэтому наш путь — в functions.php.

Нам необходимо создать новый action для для хука rest_api_init, который поможет нам создать новый маршрут для REST API:

// Энд-поинты приложения
add_action('rest_api_init', function() {

});

Как видите, к хуку ‘rest_api_init’ я добавил неименованную функцию, потому что у нас будет несколько маршрутов.

Авторизация пользователя

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

Напишем первую функцию маршрута и разберёмся, что же здесь написано.

// Маршрут авторизации
register_rest_route('api/', 'auth/', [
    'methods' => 'POST',
    'callback' => 'auth',
    'args' => array(
        'login' => array(
            'default' => $login
        ),
        'password' => array(
            'default' => $pass
        ),
    ),
]);

Первые два аргумента функции — это переменные адреса, по которому мы будем посылать запрос, что соответсвует такому адресу:

https://awesomesite.com/wp-json/api/auth

Далее, в параметре ‘methods’ мы определяем метод, с помощью которого мы данные отправим (POST).

Параметр ‘callback’ вызывает функцию, которая должна будет сработать при обращении на этот адрес.

И наконец параметр ‘args’ массивом указывает, какие ключи в этом запросе имеются. В нём мы указываем, что передаем на обработку логин пользователя и пароль.

Строим запрос от приложения

Первый роут готов, мы пока его оставим в таком виде и ненадолго отвлечёмся от WordPress и вернемся к нашему приложению — давайте посмотрим, как мы будем такой запрос строить.

Мы уже договорились, что подробно расписывать устройство JS-приложения не будем. Условимся, что в нашем приложении при первоначальной загрузке мы просим указать пользователя email и пароль. После того, как он эти данные ввёл, мы передаем эти данные примерно вот таким образом:

// Формируем объект из логина и пароля пользователя
let data = { login, password };

// Адрес к энд-поинту авторизации
let pathToAPI = 'https://awesomesite.com/wp-json/api/auth';

// Запрос
fetch(pathToAPI, {
    method: 'POST',
    body: JSON.stringify(data),
    headers: {
        'content-type': 'application/json'
    }
    }).then((response) => {
        return response.json();
    }).then((data) => {
        handle(data);
    })

Мы написали простейший fetch-запрос (настолько простейший, что даже catch не указали), с помощью которого забросим данные по нужному нам адресу.

Здесь я вынес адрес в отдельную переменную, чтобы лучше воспринимался визуально. Рекомендую сделать функцию, которая будет в зависимости от нужной операции возвращать соответствующий адрес к API.

Также обратите внимание на headers — там обязательно нужно указать строку ‘content-type’: ‘application/json’, иначе магии не получится.

Обрабатываем запрос

Теперь, когда практически всё готово, мы возвращаемся в WordPress и напишем обработчик запроса по маршруту авторизации.

Сначала обдумаем схему работы функции (это полезно и экономит время). Вот мы отправили логин (email) и пароль серверу. Он их должен проверить и если такой пользователь существует, то вернуть нам его ID. А если нет — то сообщить, что введённые данные неправильные.

Используя стандартные функции WordPress, напишем такую функцию, её работу прокомментирую прям по ходу:

// Функция авторизации пользователя
function auth($request) {

    // Вытаскиваем в отдельные переменные ключи из запроса
    $login = $request['login'];
    $password = $request['password'];

    // Проверяем пользователя
    $auth = wp_authenticate($login, $password);

    // Если ошибки нет
    if (!is_wp_error($auth)) {

        // Получаем id пользователя по email
        $user = get_user_by('email', $login);
        $user_ID = $user->data->ID;

        // Формируем объект ответа
        $response = array(
            "id" => $user_ID
        );
    
    // В случае ошибки
    } else {
        $response = array(
            "state" => 'error',
            "response" => 'Неправильный логин / пароль'
        );
    }
    
    // Возвращаем объект ответа
    return $response;
}

Итак, первый маршрут готов. Можем попробовать послать запрос от приложения к API и получить ответ в виде объекта, который уже нужным нам образом можно обработать.

Запрос данных

Перейдем ко второму маршруту — запросим список последних постов для пользователя. Аналогичным образом добавляем новый роут для API:

// Маршрут получения постов
register_rest_route('api/', 'posts/', [
    'methods'  => 'POST',
    'callback' => 'getPosts',
    'args' => array(
        'id' => array(
            'default' => $id
        ),
        'type' => array(
            'default' => $type
        ),
        'counts' => array(
            'default' => $counts
        ),
    ),
]);

Здесь повысим ставки — теперь нам нужно 3 параметра передать: это id пользователя (зачем-то мы его получали же!), тип поста и количество постов.

Теперь напишем саму функцию по обработке:

// Функция авторизации пользователя
function getPosts($request) {

    // Вытаскиваем в отдельные переменные ключи из запроса
    $id = $request['id'];
    $type = $request['type'];
    $counts = $request['counts'];

    // Если id передано
    if($id) {

        // Массив постов
        $posts = array();

        // Формируем запрос с помощью WP_Query
        $query = new WP_Query(array(
            'post_type' =>  $type,
            'posts_per_page' => $counts
        ));

        // Пройдемся по массиву
        while ($query->have_posts()) : $query->the_post();

            // Получаем заголовок и описание
            $title = esc_html(get_the_title());
            $desc = get_the_excerpt();
        
            // Получаем ссылку на изображение (если оно есть)
            if(has_post_thumbnail()) {
                $thumb_id = get_post_thumbnail_id();
                $thumb_cover_url = wp_get_attachment_image_src($thumb_id, full, true);
                $imgUrl = $thumb_cover_url[0];
            } else {
                $imgUrl = 'null'; // Или можно указать ссылку на картинку-заглушку
            }
        
            // Формируем объект поста
            $post = array(
                "title" => $title,
                "description" => $desc,
                "img" => $imgUrl
            );

            // Добавляем его в массив постов
            array_push($posts, $post);

        endwhile; wp_reset_postdata();

        // Ответ - это массив постов
        $response = $posts;

    // В случае, если id передано
    } else {
        $response = array(
            "state" => 'error',
            "response" => 'Мне нужен ID'
        );
    }

    
    // Возвращаем объект ответа
    return $response;
}

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

У нас даже получилось лучше, чем в стандартной реализации, потому что отдаётся меньший по составу объект и кроме того, у нас уже имеется ссылка на изображение-обложку поста, а не только ID медиафайла.

Итого

Вот так с помощью WordPress и его немудрёного функционала можно достаточно быстро собрать себе API для приложения. Осталось только взять любимый фреймворк и наладить взаимодействие.

Надеюсь, что материал будет полезен для вас и поможет разрешить некоторые трудности.

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

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

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