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