Wp_query фильтровать по одному полю, а сортировать по-другому?
Всем привет.
Столкнулся с проблемой.
У поста есть 2 custom fields.
loop_event_date - дата, когда произойдет мероприятие.
featured - Закрепить как первое в списке.
add_action('rest_api_init', 'eventsApiPosts'); function eventsApiPostsFunc($data) { $term_slug = $data['term_slug'] ?? null; $date = $data['date']; $now = date('Y-m-d'); $current_page = $data['current_page']; $lang = $data['lang']; if ($date) { if ($date === 'coming-soon') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '>', 'type' => 'DATE' ) ); } else if ($date === 'past-events') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '<', 'type' => 'DATE' ) ); } else { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $date, 'compare' => 'LIKE' ) ); } } $tax_query = []; if ($term_slug) { $tax_query = array( array( 'taxonomy' => 'events_category', 'field' => 'slug', 'terms' => [$term_slug], ) ); } $post_type = 'events'; $posts_per_page = 3; $offset = ($current_page * $posts_per_page) - $posts_per_page; $post_events = new WP_Query(array( 'post_type' => $post_type, 'order' => 'ASC', 'posts_per_page' => $posts_per_page, 'offset' => $offset, 'tax_query' => $tax_query, 'meta_key' => 'loop_event_date', // Meta key for filtering 'orderby' => 'meta_value', // Order by meta value 'order' => 'ASC', // Order direction, you can change this t 'meta_query' => $meta_query, 'meta_key' => 'featured', // Meta key for sorting 'orderby' => 'meta_value', // Order by meta value as numeric 'order' => 'ASC', )); $total_posts = $post_events->found_posts; $pages = ceil($total_posts / $posts_per_page); $events_array = $post_events->get_posts(); $events_array = array_map(function ($event) use ($lang) { $id = $event->ID; $title = get_the_title($id); $term = get_the_terms($id, 'events_category')[0]; if ($lang === 'ro') { $location = get_field('title_ro', $term); } else { $location = $term->name; } $loop = get_field('loop', $id); $event_date = $loop['event_date']; $short_description = $loop['short_description']; $image = get_the_post_thumbnail_url($id); return [ 'id' => $id, 'title' => $title, 'location' => $location, 'event_date' => $event_date, 'featured' => get_field('featured', $id), 'short_description' => $short_description, 'image' => $image, 'lang' => $lang, 'term_name' => $term->name, 'permalink' => get_the_permalink($id), ]; }, $events_array); $count = count($events_array); return [ 'lang' => $lang, 'total' => $total_posts, 'count' => $count, 'pages' => $pages, 'current_page' => $current_page, 'events' => $events_array, 'offset' => $offset, 'current_page' => $current_page, 'posts_per_page' => $posts_per_page, ]; } |
add_action('rest_api_init', 'eventsApiPosts'); function eventsApiPostsFunc($data) { $term_slug = $data['term_slug'] ?? null; $date = $data['date']; $now = date('Y-m-d'); $current_page = $data['current_page']; $lang = $data['lang']; if ($date) { if ($date === 'coming-soon') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '>', 'type' => 'DATE' ) ); } else if ($date === 'past-events') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '<', 'type' => 'DATE' ) ); } else { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $date, 'compare' => 'LIKE' ) ); } } $tax_query = []; if ($term_slug) { $tax_query = array( array( 'taxonomy' => 'events_category', 'field' => 'slug', 'terms' => [$term_slug], ) ); } $post_type = 'events'; $posts_per_page = 3; $offset = ($current_page * $posts_per_page) - $posts_per_page; $post_events = new WP_Query(array( 'post_type' => $post_type, 'order' => 'ASC', 'posts_per_page' => $posts_per_page, 'offset' => $offset, 'tax_query' => $tax_query, 'meta_key' => 'loop_event_date', // Meta key for filtering 'orderby' => 'meta_value', // Order by meta value 'order' => 'ASC', // Order direction, you can change this t 'meta_query' => $meta_query, 'meta_key' => 'featured', // Meta key for sorting 'orderby' => 'meta_value', // Order by meta value as numeric 'order' => 'ASC', )); $total_posts = $post_events->found_posts; $pages = ceil($total_posts / $posts_per_page); $events_array = $post_events->get_posts(); $events_array = array_map(function ($event) use ($lang) { $id = $event->ID; $title = get_the_title($id); $term = get_the_terms($id, 'events_category')[0]; if ($lang === 'ro') { $location = get_field('title_ro', $term); } else { $location = $term->name; } $loop = get_field('loop', $id); $event_date = $loop['event_date']; $short_description = $loop['short_description']; $image = get_the_post_thumbnail_url($id); return [ 'id' => $id, 'title' => $title, 'location' => $location, 'event_date' => $event_date, 'featured' => get_field('featured', $id), 'short_description' => $short_description, 'image' => $image, 'lang' => $lang, 'term_name' => $term->name, 'permalink' => get_the_permalink($id), ]; }, $events_array); $count = count($events_array); return [ 'lang' => $lang, 'total' => $total_posts, 'count' => $count, 'pages' => $pages, 'current_page' => $current_page, 'events' => $events_array, 'offset' => $offset, 'current_page' => $current_page, 'posts_per_page' => $posts_per_page, ]; }
Так отоображаются 6 постов, но при добавлении
'meta_key' => 'featured', // Meta key for sorting 'orderby' => 'meta_value', // Order by meta value as numeric 'order' => 'ASC', |
'meta_key' => 'featured', // Meta key for sorting 'orderby' => 'meta_value', // Order by meta value as numeric 'order' => 'ASC',
Только 3.
Дополнительные вопросы
Ответы:
Во первых у вас повторяются ключи в аргументах wp query
Второе - вы уверены что ваш код располагается где надо ?
Отображается три потому что у трех других вероятно отсутствует мета featured. Вам надо compare exists
- Я его немного поменял
function eventsApiPosts() { register_rest_route('events/v1', 'posts', [ 'methods' => WP_REST_SERVER::READABLE, 'callback' => 'eventsApiPostsFunc', ]); } add_action('rest_api_init', 'eventsApiPosts'); function eventsApiPostsFunc($data) { $term_slug = $data['term_slug'] ?? null; $date = $data['date']; $now = date('Y-m-d'); $current_page = $data['current_page']; $lang = $data['lang']; if ($date) { if ($date === 'coming-soon') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '>', 'type' => 'DATE' ) ); } else if ($date === 'past-events') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '<', 'type' => 'DATE' ) ); } else { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $date, 'compare' => 'LIKE' ) ); } } $tax_query = []; if ($term_slug) { $tax_query = array( array( 'taxonomy' => 'events_category', 'field' => 'slug', 'terms' => [$term_slug], ) ); } $post_type = 'events'; $posts_per_page = 3; $offset = ($current_page * $posts_per_page) - $posts_per_page; $post_events = new WP_Query(array( 'post_type' => $post_type, 'posts_per_page' => $posts_per_page, 'offset' => $offset, 'tax_query' => $tax_query, 'meta_query' => $meta_query, // 'orderby' => 'meta_value', // Order by meta value as numeric // 'meta_key' => 'featured', // Meta key for sorting // 'meta_type' => 'DATE', // Meta type // 'order' => 'DESC', )); $total_posts = $post_events->found_posts; $pages = ceil($total_posts / $posts_per_page); $events_array = $post_events->get_posts(); $events_array = array_map(function ($event) use ($lang) { $id = $event->ID; $title = get_the_title($id); $term = get_the_terms($id, 'events_category')[0]; if ($lang === 'ro') { $location = get_field('title_ro', $term); } else { $location = $term->name; } $loop = get_field('loop', $id); $event_date = $loop['event_date']; $short_description = $loop['short_description']; $image = get_the_post_thumbnail_url($id); return [ 'id' => $id, 'title' => $title, 'location' => $location, 'event_date' => $event_date, 'featured' => get_field('featured', $id), 'short_description' => $short_description, 'image' => $image, 'lang' => $lang, 'term_name' => $term->name, 'permalink' => get_the_permalink($id), ]; }, $events_array); $count = count($events_array); return [ 'lang' => $lang, 'total' => $total_posts, 'count' => $count, 'pages' => $pages, 'current_page' => $current_page, 'events' => $events_array, 'offset' => $offset, 'current_page' => $current_page, 'posts_per_page' => $posts_per_page, ]; }
function eventsApiPosts() { register_rest_route('events/v1', 'posts', [ 'methods' => WP_REST_SERVER::READABLE, 'callback' => 'eventsApiPostsFunc', ]); } add_action('rest_api_init', 'eventsApiPosts'); function eventsApiPostsFunc($data) { $term_slug = $data['term_slug'] ?? null; $date = $data['date']; $now = date('Y-m-d'); $current_page = $data['current_page']; $lang = $data['lang']; if ($date) { if ($date === 'coming-soon') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '>', 'type' => 'DATE' ) ); } else if ($date === 'past-events') { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $now, 'compare' => '<', 'type' => 'DATE' ) ); } else { $meta_query = array( array( 'key' => 'loop_event_date', 'value' => $date, 'compare' => 'LIKE' ) ); } } $tax_query = []; if ($term_slug) { $tax_query = array( array( 'taxonomy' => 'events_category', 'field' => 'slug', 'terms' => [$term_slug], ) ); } $post_type = 'events'; $posts_per_page = 3; $offset = ($current_page * $posts_per_page) - $posts_per_page; $post_events = new WP_Query(array( 'post_type' => $post_type, 'posts_per_page' => $posts_per_page, 'offset' => $offset, 'tax_query' => $tax_query, 'meta_query' => $meta_query, // 'orderby' => 'meta_value', // Order by meta value as numeric // 'meta_key' => 'featured', // Meta key for sorting // 'meta_type' => 'DATE', // Meta type // 'order' => 'DESC', )); $total_posts = $post_events->found_posts; $pages = ceil($total_posts / $posts_per_page); $events_array = $post_events->get_posts(); $events_array = array_map(function ($event) use ($lang) { $id = $event->ID; $title = get_the_title($id); $term = get_the_terms($id, 'events_category')[0]; if ($lang === 'ro') { $location = get_field('title_ro', $term); } else { $location = $term->name; } $loop = get_field('loop', $id); $event_date = $loop['event_date']; $short_description = $loop['short_description']; $image = get_the_post_thumbnail_url($id); return [ 'id' => $id, 'title' => $title, 'location' => $location, 'event_date' => $event_date, 'featured' => get_field('featured', $id), 'short_description' => $short_description, 'image' => $image, 'lang' => $lang, 'term_name' => $term->name, 'permalink' => get_the_permalink($id), ]; }, $events_array); $count = count($events_array); return [ 'lang' => $lang, 'total' => $total_posts, 'count' => $count, 'pages' => $pages, 'current_page' => $current_page, 'events' => $events_array, 'offset' => $offset, 'current_page' => $current_page, 'posts_per_page' => $posts_per_page, ]; }
- Сергей Бурдужа, делайте ассоциативные мета запросы и потом сортируйте по ним
если у вас featured поле может отсутвутвовать для записей - делайте для него OR запрос с EXISTS
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос
В
WP_Queryможно фильтровать по одному custom field, а сортировать по другому. Для этого используйте именованные условия вmeta_queryи указывайте нужное условие вorderby. В вашем случае, например, можно отфильтровать мероприятия по дате, а закреплённые выводить выше через полеfeatured.Общий пример:
$query = new WP_Query([ 'post_type' => 'events', 'posts_per_page' => 10, 'meta_query' => [ 'relation' => 'AND', 'event_date_clause' => [ 'key' => 'loop_event_date', 'value' => date('Y-m-d'), 'compare' => '>=', 'type' => 'DATE', ], 'featured_clause' => [ 'key' => 'featured', 'compare' => 'EXISTS', 'type' => 'NUMERIC', ], ], 'orderby' => [ 'featured_clause' => 'DESC', 'event_date_clause' => 'ASC', ], ]);
Если поле
featuredесть не у всех записей, сортировка может вести себя неожиданно. Тогда лучше при сохранении записи всегда записывать туда0или1, а не оставлять поле пустым.Для REST API не забывайте чистить входные параметры:
$date = isset($data['date']) ? sanitize_text_field($data['date']) : ''; $current_page = max(1, (int) ($data['current_page'] ?? 1));
Если нужно показывать будущие мероприятия, фильтруйте дату через
meta_query. Если нужно дополнительно закреплять некоторые записи сверху, сортируйте сначала поfeatured, потом по дате. Главное — указывать правильныйtype: для датDATE, для чиселNUMERIC. Иначе WordPress будет сортировать значения как строки.