Замена admin-ajax на REST API эндпоинты

Иногда может быть удобно заменить ajax запросы в админке на запросы с использованием REST API. Это может сделать ваш код более лаконичным, а запросы более безопасными.

Давайте рассмотрим следующий пример. Допустим код плагина добавляет страницу админки. На этой странице есть кнопка и область для результата AJAX запроса. При клике на кнопку выполняется ajax-запрос который получает последние записи, затем заголовки этих записей отображаются.

Использование WP AJAX

В этом примере нет реализации nonce для безопасности, но это обязательно нужно добавить в реальном плагине.

Для начала нужно подключить наш JS скрипт:

add_action( 'admin_enqueue_scripts', 'wp_learn_rest_enqueue_script' );

function wp_learn_rest_enqueue_script() {
	wp_enqueue_script(
		'myscript',
		plugin_dir_url( __FILE__ ) . 'myscript.js',
		[ 'jquery' ],
		false,
		true
	);
}

Теперь напишем скрипт для обработки события нажатия на кнопку и выполнения Ajax-запроса.

/**
 * Обработка Ajax-запроса
 */
jQuery( document ).ready(
	function ( $ ) {
		const loadPostsButton = $( '#ajax-button' );
		if ( loadPostsButton ) {
			loadPostsButton.on(
				'click',
				function ( event ) {
					$.post(
						ajaxurl,
						{
							'action': 'learn_fetch_posts',
						},
						function ( posts ) {
							const textarea = $( '#wp-learn-posts' );
							posts.forEach( function ( post ) {
								textarea.append( post.post_title + '\n' )
							} );
						},
					)
				},
			);
		}
	},
);

Заметка: Тут мы используем js переменную ajaxurl, которая автоматически определена в адмни-панели.

Теперь нужно создать функцию для обработки ajax-запроса. Для этого вешаем коллбэк на хук wp_ajax_*

add_action( 'wp_ajax_learn_fetch_posts', 'my_ajax_fetch_posts' );

function my_ajax_fetch_posts() {
	$posts = get_posts();
	wp_send_json( $posts );

	// Все обработчики ajax должны прекратить работу PHP по завершению своей работы
	wp_die();
}

Использование WP REST API

Теперь рассмотрим как такая задача будет выглядеть, если использовать WP REST API.

Теперь не нужен обработчик ajax-запроса, поэтому можем удалить функцию my_ajax_fetch_posts и связанный хук.

WordPress поставляется с клиентом Backbone JavaScript для выполнения прямых запросов к WP REST API.

Чтобы убедиться, что ваш код может использовать клиент Backbone.js, вам просто нужно обновить зависимость вашего плагина с jquery на wp-api.

Это обеспечит загрузку JavaScript-кода вашего плагина только после загрузки JavaScript-клиента REST API, чтобы вы могли использовать его в вашем js скрипте.

В JavaScript-файле сначала вы можете удалить код, связанный с jQuery/Ajax.

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

const loadPostsByRestButton = document.getElementById( 'wp-learn-rest-api-button' );
if ( loadPostsByRestButton ) {
	loadPostsByRestButton.addEventListener( 'click', function () {
		// сделать что-то
	} );
}

Затем в функции обработчика событий вы можете использовать WP API client, получая его из глобального объекта wp, чтобы создать новую коллекцию записей:

const allPosts = new wp.api.collections.Posts();

На этом этапе "allPosts" — это просто пустая коллекция, поэтому вам нужно будет получить записи, вызвав метод "fetch" на коллекции.

allPosts.fetch();

Метод "fetch" возвращает промис, поэтому вы можете цепочкой использовать метод done для обработки ответа и реализовать функцию обратного вызова, которая примет ответ от запроса API. Вы можете указать аргумент posts в этой функции обратного вызова, чтобы принять ответ от запроса API

const posts = allPosts.fetch().done(
	function ( posts ) {
		// сделать что-то с записями
	}
);

Теперь можно перебрать объект posts, используя метод "forEach".

const posts = allPosts.fetch().done(
	function ( posts ) {
		posts.forEach( function ( post ) {
			// сделать что-то с записью
		} );
	}
);

Наконец, можно добавить заголовок записи в область результат ответа. Сначала вам нужно создать экземпляр текстовой области перед циклом forEach, а затем добавить заголовок записи к свойству value текстовой области внутри цикла forEach.

const posts = allPosts.fetch().done(
	function ( posts ) {
		const textarea = document.getElementById( 'wp-learn-posts' );
		posts.forEach( function ( post ) {
		  textarea.value += post.title.rendered + '\n'
		} );
	}
);

Финальный код будет выглядеть примерно так:

const loadPostsByRestButton = document.getElementById( 'wp-learn-rest-api-button' );
if ( loadPostsByRestButton ) {
	loadPostsByRestButton.addEventListener( 'click', function () {
		const allPosts = new wp.api.collections.Posts();
		allPosts.fetch().done(
			function ( posts ) {
				const textarea = document.getElementById( 'wp-learn-posts' );
				posts.forEach( function ( post ) {
					textarea.value += post.title.rendered + '\n'
				} )
			}
		);
	} );
}

Заключение

Большое преимущество использования WP REST API и JavaScript-клиента Backbone.js заключается в том, что вы можете использовать один и тот же клиент снова и снова. Например, если вы хотите получить пользователей, вы можете просто создать новую коллекцию пользователей и получить их. Чтобы сделать это через admin-ajax, вам потребуется либо новая функция обработчика admin_ajax, либо обновить существующую функцию, чтобы она принимала параметр для определения того, что получать.

Другим преимуществом является то, что API JavaScript-клиент обрабатывает проверку nonce за вас. С admin-ajax вам нужно указывать это самостоятельно и проверять в вашей функции обработчика. Таким образом, используя REST API и JavaScript-клиент, ваши запросы становятся более безопасными.