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 для приложения. Осталось только взять любимый фреймворк и наладить взаимодействие.
Надеюсь, что материал будет полезен для вас и поможет разрешить некоторые трудности.