Сортировка по DESC, ASC в пользовательском WP_Query
Мне нужно выполнить многоуровневую сортировку в запросе. Проблема заключается в сортировке одного значения по DESC, а другого по ASC, как в SQL. Следующий SQL-запрос дает мне то, что я хочу, когда я запускаю его в терминале:
SELECT DISTINCT * FROM wp_posts
INNER JOIN wp_postmeta
ON wp_posts.ID = wp_postmeta.post_id
WHERE wp_posts.post_type = 'post'
AND wp_postmeta.meta_key = 'pb_issue_featured'
AND wp_posts.post_status = 'publish'
ORDER BY wp_postmeta.meta_value DESC, wp_posts.menu_order ASC;
pb_issue_featured
- это булево значение. Результат, который мне нужен - это чтобы запрос отображал записи, имеющие метазначение 1 для этого поля вверху, а все остальные - внизу. Затем вторичная сортировка должна быть по назначенному menu_order
(я использую плагин post types order).
Проблема в том, что моё булево значение должно сортироваться от высокого к низкому (от 1 к 0), а menu_order наоборот. То, что сортируется первым с помощью плагина, имеет menu_order равный 1. Поэтому использование встроенного 'orderby' в WP_Query не работает. Есть ли у кого-нибудь предложения? Я рассматривал фильтр 'posts_orderby', но не смог заставить его работать. Я не был уверен, где его нужно применять или как я мог бы отладить его. Он просто не менял порядок сортировки так, как я задавал.
Спасибо за помощь! Я опубликую фактический WP_Query, если это важно, но я хотел сделать это как можно короче.
Аргументы запроса:
$args = array(
'post_type' => 'post',
'meta_key' => 'pb_issue_featured',
'orderby' => 'meta_value',
'order' => 'DESC',
'post_status' => 'publish',
'posts_per_page' => $posts,
'paged' => $paged,
'meta_query' => array(
array(
'key' => 'headline',
'value' => 1,
'compare' => '!='
)
)
);
$q = new WP_Query($args);
Попробуйте это:
$args = array(
'post_type' => 'post',
'meta_key' => 'pb_issue_featured',
'orderby' => 'meta_value',
'order' => 'DESC',
'posts_per_page' => $posts,
'paged' => $paged,
'paged' => 1,
'meta_query' => array(
array(
'key' => 'headline',
'value' => 1,
'compare' => '!='
)
)
);
add_filter( 'posts_orderby', 'filter_query' );
$q = new WP_Query($args);
remove_filter( 'posts_orderby', 'filter_query' );
function filter_query( $query ) {
$query .= ', wp_posts.menu_order ASC';
return $query;
}

Начиная с WordPress 4.0, благодаря изменению 29027 от 08.07.2014, стало возможным передавать массив для параметра orderby
, согласно статье Более мощный ORDER BY в WordPress 4.0.
В версии 4.0 вы можете передавать массив в
WP_Query
в качестве значения дляorderby
. Синтаксис выглядит так:$q = new WP_Query( array( 'orderby' => array( 'title' => 'DESC', 'menu_order' => 'ASC' ) ) );
Это позволяет контролировать генерацию конструкции
ORDER BY
с большей точностью:ORDER BY post_title DESC, menu_order ASC
До версии 4.0 вам пришлось бы использовать сложные фильтры для SQL-запроса или конкретной конструкции. Не лучший вариант.

При использовании плагина Elementor и при наличии произвольного поля с именем date, добавьте следующее действие в файл elementor-pro/elementor-pro.php в редакторе плагинов.
add_action( 'elementor/query/my_custom_filter', function( $query ) {
$query->set( 'meta_key', 'date' ); // установка ключа мета-данных 'date'
$query->set( 'orderby', 'meta_value' ); // сортировка по значению мета-поля
$query->set( 'order', 'DESC' ); // порядок сортировки по убыванию
$query->set( 'posts_per_page', 2 ); // ограничение - 2 записи на страницу
} );

Как здесь связан Elementor? В вопросе автора и во всех последующих ответах или комментариях буквально нет ни одного упоминания об Elementor.

@TonyDjukic, вы совершенно правы насчет нерелевантности Elementor. Но поскольку Google показал мне эту страницу после поиска моей конкретной ошибки о настройке WP_Query, и мне потребовалось некоторое время, чтобы найти решение, я подумал, что это может помочь кому-то еще с такой же проблемой.
