Как сделать meta query через REST-API в WordPress 4.7+?
Я пытаюсь сделать фильтрацию через meta query, но что бы я ни пробовал, ничего не работает.
По сути, я хочу сделать такой запрос через REST API:
wp-json/wp/v2/books?meta_query[relation]=OR&meta_query[0][key]=arkivera&meta_query[0][value]=1&meta_query[0][compare]==
Я пробовал несколько разных произвольных полей, но он всегда возвращает все объекты постов.
В моем файле functions.php я добавил:
function api_allow_meta_query( $valid_vars ) {
// Объединяем массивы для добавления meta_query
$valid_vars = array_merge( $valid_vars, array( 'meta_query') );
return $valid_vars;
}
add_filter( 'rest_query_vars', 'api_allow_meta_query' );
Я пытался найти документацию по этому вопросу, но не смог, также большинство похожих вопросов не относятся к WordPress 4.7, так как filter[xxx] был удален.

Используйте фильтр rest_{CUSTOM_POST_TYPE}_query для добавления поддержки метаданных записей в WP REST API для любого типа записи.
Ознакомьтесь с Gist поиск записей по метаданным с помощью REST API.
Как использовать?
http://example.org/wp-json/wp/v2/post?meta_key=<my_meta_key>&meta_value=<my_meta_value>
Пример
Получение записей, у которых метаданное поле already-visited
имеет значение true
.
http://example.org/wp-json/wp/v2/post?meta_key=already-visited&meta_value=true
Будут выведены ТОЛЬКО записи, у которых метаданное поле already-visited
имеет значение true
.
Для справки: Поиск записей по метаданным с помощью REST API.
Доступные фильтры
- rest_post_query
- rest_page_query
- rest_attachment_query

Спасибо за это! Думаю, этот ответ с большей вероятностью должен быть принятым.

А как насчет строковых полей, если мы хотим поле со значением (не null)? Я могу получить поля latitude, которые больше определенного значения: filter[meta_key]=latitude&filter[meta_compare]=%3C&filter[meta_value]=34.7. Но мне нужно еще одно строковое поле, которое имеет значение.

Вы можете написать собственный обработчик REST для пользовательских запросов, если хотите. В вашем случае запрос можно выполнить следующим образом:
// Регистрация REST маршрута
add_action( 'rest_api_init', function () {
// Путь к маршруту мета-запроса
register_rest_route( 'tchernitchenko/v2', '/my_meta_query/', array(
'methods' => 'GET',
'callback' => 'custom_meta_query'
) );
});
// Выполнение запроса и возврат данных
function custom_meta_query(){
if(isset($_GET['meta_query'])) {
$query = $_GET['meta_query'];
// Установка аргументов на основе параметров GET
$args = array (
'relation' => $query[0]['relation'],
array(
'key' => $query[0]['key'],
'value' => $query[0]['value'],
'compare' => '=',
),
);
// Запуск пользовательского запроса
$meta_query = new WP_Query($args);
if($meta_query->have_posts()) {
// Определение пустого массива
$data = array();
// Сохранение заголовка каждой записи в массиве
while($meta_query->have_posts()) {
$meta_query->the_post();
$data[] = get_the_title();
}
// Возврат данных
return $data;
} else {
// Если нет записей
return 'Нет записей для отображения';
}
}
}
Теперь все, что вам нужно сделать, это обратиться по адресу:
wp-json/tchernitchenko/v2/my_meta_query?meta_query[relation]=OR&meta_query[0][key]=arkivera&meta_query[0][value]=1&meta_query[0][compare]==

Следующий код добавляет возможность множественных мета-запросов для всех типов записей. Он поддерживает CPT (пользовательские типы записей) и ACF (Advanced Custom Fields). Исходный код также доступен на Github.
Добавьте его в ваш function.php
add_action( 'rest_api_init', 'wp_rest_filter_add_filters' );
/**
* Добавляем необходимый фильтр к каждому типу записи
**/
function wp_rest_filter_add_filters() {
foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
add_filter( 'rest_' . $post_type->name . '_query', 'wp_rest_filter_add_filter_param', 10, 2 );
}
}
/**
* Добавляем параметр фильтра
*
* @param array $args Аргументы запроса.
* @param WP_REST_Request $request Полная информация о запросе.
* @return array $args.
**/
function wp_rest_filter_add_filter_param( $args, $request ) {
// Выходим, если параметр filter не установлен
if ( empty( $request['filter'] ) || ! is_array( $request['filter'] ) ) {
return $args;
}
$filter = $request['filter'];
if ( isset( $filter['posts_per_page'] ) && ( (int) $filter['posts_per_page'] >= 1 && (int) $filter['posts_per_page'] <= 100 ) ) {
$args['posts_per_page'] = $filter['posts_per_page'];
}
global $wp;
$vars = apply_filters( 'rest_query_vars', $wp->public_query_vars );
function allow_meta_query( $valid_vars )
{
$valid_vars = array_merge( $valid_vars, array( 'meta_query', 'meta_key', 'meta_value', 'meta_compare' ) );
return $valid_vars;
}
$vars = allow_meta_query( $vars );
foreach ( $vars as $var ) {
if ( isset( $filter[ $var ] ) ) {
$args[ $var ] = $filter[ $var ];
}
}
return $args;
}
По моему мнению, лучшим решением будет вынести дополнительную функцию в отдельный плагин. Таким образом, даже если пользователь сменит тему, ваши API-запросы не пострадают.
Поэтому я разработал плагин для мета-запросов в WordPress. Более того, он поддерживает ACF!
После установки просто выполните GET запрос в следующем формате.
https://domain.com/wp-json/acf/v3/customposttype?filter[meta_key]=acfkey&filter[meta_value]=acfvalue
Исходный код плагина доступен на Github.

Отличный плагин, но сортировка по дате не работает для полей ACF с типом дата!

Привет, Tanckom. Спасибо за ваше сообщение. Не могли бы вы подробнее описать вашу проблему? Что вы уже пробовали? Пожалуйста, создайте тикет на https://wordpress.org/support/plugin/wp-rest-filter. Наша служба поддержки свяжется с вами там. Спасибо.

Привет, Jack, Я разобрался, что правильный URL для получения даты из поля ACF и сортировки по возрастанию или убыванию выглядит так: https://domain.com/wp-json/wp/v2/events?filter[meta_key].acf=evt_date&per_page=100&filter[order]=asc

Один вопрос: как можно фильтровать даты в формате "2018-09-25 19:30:00 GMT+02:00"? Date and Time Picker для ACF не поддерживает ISO-формат :( Пробовал так, но без успеха domain.com/wp-json/wp/v2/events?filter[meta_key].acf=date&[meta_value]=2018-09-25

Преобразуйте в GMT время в формате yyyy-mm-dd'T'HH:mm:ss, затем domain.com/wp-json/wp/v2/events?filter[meta_key]=date&[meta_value]=2018-09-25T23:59:59. Я полагаю, что ACF сохраняет данные в формате IOS в MySQL, поэтому это должно сработать.

К сожалению, невозможно получить Дату и Время без пробелов с помощью дополнения ACF "Date and Time Picker" :/ Именно поэтому мне пришлось сделать таким образом.
