Intereting Posts
WooCommerce 3.2.4 Короткие коды с фильтром продуктов как опубликовать фид сообщений с определенным значением поля? Внутренняя ошибка 500, доступ к теме> Настроить Добавить ссылку в приложение для старых сообщений Указание размера при отображении изображения, связанного с таксономией через ACF Переписывание URL с дочерними страницами Возможно ли нам использовать режим основного обслуживания WP для короткой паузы во время работы плагина? Извлечение изображений галереи в WordPress 3.5 на index.php Огромное количество 404 страниц, которые появляются WordPress – Скрыть сообщения в администраторе от пользователя, который их не писал WP REST api возвращает бессмысленный символ показать изображение автора в сообщениях Общий боковой бар для нескольких веб-сайтов Обновление не работает и темы, не поддерживающие WordPress «Категории для конвертеров тегов» не работает. Вместо указания import.php

Заказывать сообщения в соответствии с определенным пользователем порядком для метазначений?

Я создал несколько CPT и сохранил мета-ключ / val для каждого из них. Когда я получаю эти сообщения, мне нужно упорядочить их по значению meta, но порядок значений meta будет определен мной в массиве . Значение по умолчанию для метазначений является либо алфавитным, либо численным , что я не хочу.

Я объясню это в примере:

Post 1 => Meta key: Fruit Meta value: Apple Post 2 => Meta key: Fruit Meta value: Melon Post 3 => Meta key: Fruit Meta value: Guava Post 4 => Meta key: Fruit Meta value: Banana 

Я получаю заказ от внешнего источника, и я хочу получить сообщения в этом порядке. Пример: Я получаю заказ в массиве: ['Apple', 'Banana', 'Guava', 'Melon'] . Когда я привожу CPT, мне нужно получить их в этом порядке. (Игнорируйте алфавитный порядок, я просто пытаюсь дать общий пример).

Как достичь этого, используя meta_query или любое другое решение?

Если есть существующий поток, перенаправите меня на него.

Solutions Collecting From Web of "Заказывать сообщения в соответствии с определенным пользователем порядком для метазначений?"

Мое предлагаемое решение уже опубликовано by @cybmeta (+1), но я все равно добавляю его, поскольку он имеет дело с ним в общем виде 😉

Аналогичным образом параметры WP_Query :

 'post__in' => [1,2,3], 'orderby' => 'post__in' 

используйте пользовательский заказ:

 ORDERBY FIELD( wp_posts.ID, 1, 2, 3 ) 

мы можем определить наш собственный мета-заказ, используя:

 'meta__in' => [ 'apple', 'orange', 'banana' ], 'orderby' => 'meta__in' 

для получения следующей части SQL:

 ORDERBY FIELD( wp_postmeta.meta_value, 'apple', 'orange', 'banana' ) 

Сначала мы определяем нашу собственную версию вспомогательной функции wp_parse_id_list() .

 /** * Note that this function is based on the core wp_parse_id_list() function. * Clean up an array, comma- or space-separated list of string keys. * * @uses sanitize_key() * @param array|string $list List of keys. * @return array Sanitized array of keys. */ function wpse_parse_meta_list( $list ) { if ( ! is_array( $list ) ) $list = preg_split('/[\s,]+/', $list); return array_unique( array_map( 'sanitize_key', $list ) ); } 

Демо-плагин

Затем мы создаем следующий демонстрационный плагин, чтобы добавить поддержку для 'meta__in' в WP_Query :

 <?php /** * Plugin Name: Support for order by meta__in in WP_Query */ add_filter( 'posts_orderby', function ( $orderby, \WP_Query $q ) { if( $meta__in = $q->get( 'meta__in' ) ) { if( is_array( $meta__in ) && ! empty( $meta__in ) ) { global $wpdb; // Transform the meta__in array into a comma separated strings of keys // Example [ 'apple', 'banana' ] --> "apple", "banana" $list = '"' . join( '","', wpse_parse_meta_list( $meta__in ) ) . '"'; // Override the orderby part with custom ordering: $orderby = " FIELD( {$wpdb->postmeta}.meta_value, {$list} ) "; } } return $orderby; }, 10, 2 ); /** * Note that this function is based on the core wp_parse_id_list() function. * Clean up an array, comma- or space-separated list of string keys. * * @uses sanitize_key() * @param array|string $list List of keys. * @return array Sanitized array of keys. */ function wpse_parse_meta_list( $list ) { if ( ! is_array( $list ) ) $list = preg_split('/[\s,]+/', $list); return array_unique( array_map( 'sanitize_key', $list ) ); } 

где мы добавили вспомогательную функцию в плагин.

Заметки

Мы используем параметр 'meta__in' для упорядочения, а не для дополнительных ограничений WHERE , как у нас с параметром 'post__in' . Но это может быть интересным продолжением 😉

Также обратите внимание, что get_posts() , это только оболочка WP_Query , по умолчанию имеет следующий параметр:

 'suppress_filters' => true 

т.е. он не принимает фильтры posts_* по умолчанию.

Поэтому, если вы не можете использовать WP_Query или get_posts() с suppress_filters => false , вам понадобится альтернативный подход, например, предложенный @PieterGoosen.

Если значение мета-поля является единственным значением (не сериализованным), этот фильтр может работать:

 add_filter( 'posts_orderby', 'custom_posts_orderby' ); function custom_posts_orderby( $orderby_statement ) { $custom_order = array( 'Apple', 'Banana', 'Guava', 'Melon' ); $custom_order = implode ( ", ", $custom_order ); $orderby_statement = "FIELD( meta_value, " . $custom_order . " )"; return $orderby_statement; } 

Обратите внимание, что это повлияет на все запросы, поэтому вам необходимо определить условия для применения фильтра или нет.

Вы можете увидеть больше примеров для создания statemnet ORDER BY FIELD() в этом сообщении .

Как я уже сказал, IMHO, с вашим лучшим вариантом для того, что вам нужно, будет usort() для сортировки возвращаемого массива сообщений

Вот непроверенная теория

 $sortorder = ['Apple', 'Banana', 'Guava', 'Melon']; $args = [ 'meta_query' => [ [ 'key' => 'Fruit', 'value' => $sortorder ] ], ]; $q = new WP_Query( $args ); @usort( $q->posts, function( $a, $b ) use ( $sortorder ) { // Get the meta values from the two posts to be compared $array_a = get_post_meta( $a->ID, 'Fruit', true ); $array_b = get_post_meta( $b->ID, 'Fruit', true ); // Reverse our $sortorder, key/value becomes value/key $flipped_order = array_flip( $sortorder ); // Let start our sorting // If our meta values are the same order by date if ( $flipped_order[$array_a] != $flipped_order[$array_b] ) { return $flipped_order[$array_a] - $flipped_order[$array_b] // Swop around to reverse ordering } else { return $a->post_date < $b->post_date; // Change to > if you need oldest posts first } }); // Run your loop normally 

РЕДАКТИРОВАТЬ

Я не ввел никакой безопасности в свой код. Вы хотели бы удостовериться, что $sortorder является допустимым массивом, тогда вам нужно дезинфицировать и проверять значения, прежде чем использовать их, чтобы избежать вредоносного кода.

Вы можете сделать это и для основного запроса, но единственное, что вы хотели бы обернуть usort() в фильтр the_posts а затем использовать $posts вместо $q->posts