Я модифицировал встроенный поиск WP с помощью pre_get_posts
фильтра, позволяющего пользователю сортировать сообщения (включая несколько пользовательских типов сообщений) по разным полям.
Проблема, с которой я столкнулся, заключается в том, что когда я говорю WP сортировать по мета-значению, он исключает все посты, для которых это мета-значение не установлено. Это приводит к изменению количества результатов, если вы измените сортировку, скажем, «Цена» на «Дата», потому что для «Сообщений» не установлена «Цена», а для «Предметов».
Это не то, что я хочу, поэтому я хотел бы знать, есть ли способ включить ВСЕ посты - даже те, в которых отсутствует мета-значение, по которому я сортирую, - и поместить одно без значения last.
Я знаю, как сортировать по нескольким полям, но это не помогает.
Благодарность
Кажется, я не единственный, кто задается этим вопросом: как включить в аргументы для wp_query сообщения с мета-ключом и без него? но там нет решения.
Обновить
Я попробовал ответ, но не уверен, правильно ли я понял, вот что у меня сейчас:
<?php
function my_stuff ($qry) {
$qry->set('meta_query', array(array(
'key' => 'item_price',
'value' => '',
'compare' => 'NOT EXISTS'
)));
$qry->set('orderby', 'meta_value date'); # Sorting works with meta_value as well as meta_value_num - I've tried both
$qry->set('order', 'ASC DESC');
$qry->set('meta_key', 'item_price');
}
Мета-значение - это число (оно используется для хранения цены, как следует из названия)
Обновление 2
Я закомментировал материал заказа, и все, что у меня сейчас есть, это:
<?php
$qry->set('meta_query', array(array(
'key' => 'item_price',
'value' => '',
'compare' => 'NOT EXISTS'
)));
С этим кодом запрос, кажется, возвращает все сообщения, у которых нет item_price
ключа, и ни одного из сообщений, у которых его есть. То есть проблема сейчас решена.
Если я добавлю код заказа, я получу 0 результатов.
Редактировать: ... три года спустя ... : У ПИ снова возникла эта проблема. Я перепробовал все ответы, и ни один не работал. Не уверен, почему некоторые люди думают, что они работают, но они, по крайней мере, не работают для меня.
Решение, которое я выбрал, заключается в использовании save_post
фильтра - убедитесь, что все сообщения имеют настраиваемое поле, по которому я хочу отсортировать. Это немного раздражает, я должен это делать, но если вы сделаете это рано, у вас, вероятно, не будет проблем.
В этом случае я строил «счетчик просмотров» для постов и хотел, чтобы пользователи могли сортировать наиболее читаемые посты. Опять же, посты, которые никогда не просматривались (я думаю, это довольно маловероятно - но все же) исчезали при сортировке по количеству просмотров. Я добавил этот фрагмент кода, чтобы убедиться, что все сообщения имеют количество просмотров:
add_action('save_post', function ($postId) {
add_post_meta($postId, '_sleek_view_count', 0, true);
});
источник
meta_query
иtax_query
это всегдаarray( array() )
, как они сочетают в себе несколько массивов. Второе - как уже упоминалось в моем ответе - нужно использоватьmeta_value_num
для чисел. С тем же успехом может потребоваться определениеmeta_value_num
(см.WP_Query
Запись страницы -Codex). Наконец, это не имеет смыслаorder
в направленииASC
иDESC
направлении. Это невозможно. Разделитель пространства работает только для,orderby
и вы не можете сказать ему, чтобы отсортировать первоеASC
и второеDESC
. Для этого и нуженposts_clauses
фильтр.meta_value_num
записи являются действительными числами. Слишком часто видели, что кто-то заявляет, что это число, но фактически сохраняет его в виде строки в базе данных.ASC DESC
настолько , что он сортирует наmeta_value
вASC
иdate
вDESC
, насколько я могу сказать , что это работает.Ответы:
Есть два возможных решения этого:
1. Все сообщения имеют мета
Лучшее решение, которое я нашел здесь, это дать остальным постам / продуктам цену товара 0. Вы можете сделать это вручную или просмотреть все посты, и если цена пуста, обновите ее.
Чтобы сделать это управляемым в будущем, вы можете подключиться
save_post
и дать им значение при первом добавлении (только если оно пустое).2. Несколько запросов
Вы можете выполнить первый запрос, как вы делаете, и сохранить идентификаторы возвращенных сообщений. Затем вы можете выполнить другой запрос для всех сообщений и даты заказа, исключая идентификаторы, возвращаемые из первого запроса.
Затем вы можете распечатать два результата отдельно, и вы получите желаемые результаты.
источник
save_post
метод (я обновил свой вопрос с помощью кода, который я использовал).Easy Peasy, только что протестированный 2018 год, используется в производстве в настоящее время.
Это проверяет все элементы с мета-ключом и без него, без указания значения. мета-запрос обеспечивает ключ для заказа надежно. Это было проверено. Однако я не уверен, как это будет работать, когда мета-запрос использует несколько ключей.
Практический пример
Это упорядочит сообщения по
custom_meta_key
умолчанию и не будет игнорировать сообщения без значения для этого ключа.источник
custom_meta_key
и получать посты, которые не имеютcustom_meta_key
. Не стесняйтесь включать фактический рабочий пример с сортировкой.$query->set( 'orderby', 'meta_value title' );
(Порядок по мета-значению, а затем по заголовку, когда несколько сообщений имеют одинаковое значение для мета-ключа). Это должно быть сделано вpre_get_posts
хуке, используя переданную$query
переменную in . Имейте в виду, что заданный вопрос состоял в том, как упорядочить по мета-значению, не игнорируя при этом посты, которые не имеют значения для этого мета-ключа.get_posts()
звонке, чтобы пихать посты с_featured
мета в начало, а затем упорядочивать по дате после этого. Благодарность!Этот метод вернет все сообщения, включая те, которые были запрошены и не запрошены
meta_key
, но он будет делать странные вещи при заказе.Я нашел это, возившись со всеми различными ответами на этот вопрос и анализируя сгенерированный SQL методом проб и ошибок. Кажется, что установка
array('meta_query' => array('relation' => 'OR'))
выводит соответствующийLEFT JOIN
вместо тогоINNER JOIN
, чтобы включать посты, пропускающие метаданные. Указание атрибутовNOT EXISTS
предотвращаетWHERE
отфильтровывание сообщений, в которых отсутствует метаполе. Для этогоWP_Query
, сгенерированный SQL (добавлены отступы / новые строки):Результатом является список всех сообщений с meta_value
item_price
и отсутствующихitem_price
. Все посты сitem_price
будут упорядочены правильно относительно друг друга, но в пропущенных постахitem_price
будет использоваться какое-то другое случайное мета-значение (скажем,_edit_last
которое1
довольно часто встречается в моей базе данных или некоторые другие внутренние метаданные WordPress, которые являются совершенно произвольными) для своихwp_postmeta.meta_value
вORDER BY
положение. Таким образом, хотя этот метод близок и может работать для определенных данных, он не работает. Итак, все, что я могу сказать, это то, что если вашиitem_price
значения не конфликтуют со случайными мета-полями, которые MySQL выбирает для отсутствующих сообщенийitem_price
, это может хорошо работать для вас. Если все, что вам нужно, это гарантия того, что ваши сообщения сitem_price
правильно упорядочены относительно друг друга без учета порядка других постов, это может быть в порядке. Но я думаю, что это просто недостаток в WordPress. Пожалуйста, поправьте меня, я надеюсь, что я не прав, и есть способ решить эту проблему ;-).Похоже, что для
INNER JOIN wp_postmeta
MySQL выбирается случайная строка из множестваpostmeta
строк, связанных с сообщением, когдаmeta_key
оно отсутствует в данном сообщении. С точки зрения SQL нам нужно выяснить, как сказать wordpress для выводаORDER BY mt1.meta_value
. Этот столбец правильно,NULL
когда наш запросmeta_key
отсутствует, в отличие отwp_postmeta.meta_value
. Если бы мы могли это сделать, SQL отсортировал бы этиNULL
(отсутствующие записи) перед любым другим значением, дав нам четко определенный порядок: сначала идут все сообщения, в которых отсутствует определенное поле postmeta, затем идут сообщения, имеющие поле. Но в этом вся проблема:'orderby' => 'meta_value'
может относиться только к'meta_key' => 'item_price'
и unaliasedwp_postmeta
всегда являетсяINNER JOIN
вместо когда - либоLEFT JOIN
, то естьwp_postmeta.meta_value
иwp_postmeta.meta_key
может ,никогда не будетNULL
.Поэтому я должен сказать, что это невозможно с помощью встроенного в WordPress,
WP_Query
как это теперь задокументировано (в WordPress-3.9.1). Беспокоить. Так что если вам действительно нужно, чтобы это работало правильно, вам, вероятно, нужно подключиться к WordPress в другом месте и напрямую изменить сгенерированный SQL .источник
Я думаю, что у меня есть решение.
Вы можете использовать два
meta_key
с, один, что все сообщения имеют(like "_thumbnail_id")
, и тот, которыйmeta_key
вы хотите использовать в качестве фильтра.Итак, ваши аргументы:
источник
'value' => '',
также будет работать,NOT EXISTS
и второе сравнение должно быть, и последняя команда set не требуетсяПроблема, с которой все здесь сталкиваются, связана с порядком мета-запросов. Для правильной сортировки вам нужно будет поставить перед запросом «НЕ СУЩЕСТВУЕТ» «СУЩЕСТВУЕТ».
Причина этого заключается в том, что WordPress использует значение meta_value последнего оператора «LEFT JOIN» в предложении «ORDER BY».
Например:
источник
При необходимости вы можете добавлять мета-значение по умолчанию каждый раз, когда запись сохраняется или обновляется, если мета-значение не существует.
Если вы используете пользовательский тип записи, замените
add_action('save_post', 'addDefaultMetaValue');
,add_action('save_post_{post_type}', 'addDefaultMetaValue');
например, наadd_action('save_post_product', 'addDefaultMetaValue');
источник
Я сам столкнулся с проблемой числовых мета-значений и указал, что порядок запросов также важен. Для меня
NOT EXISTS
запрос должен быть первым.Пример:
Также важно, чтобы получить правильное направление для числовых значений, является общим
’orderby’
для установки’meta_value_num’
. В противном случае вы получите странные результаты для числовых значений, например:1, 2, 20, 21, 3, 4, 5…
Вместо того:
1, 2, 3, 4, 5… 20, 21
источник
Я также столкнулся с подобной проблемой, и мне помогло следующее решение:
Я нашел описание в Кодексе WordPress с заголовком « orderby» с несколькими «meta_key's »: https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
источник
Есть возможная
orderby
ценностьmeta_value
для этого.Если вы получили числовые значения, просто используйте
meta_value_num
вместо этого.Отказ от ответственности: это не проверено, но оно должно работать. Дело в том, что вам нужно указать ваши
meta_key
иkey
значения. В противном случае вы не можете сравнить с несуществующими значениями, что должно позволить запрашивать оба вида сообщений. Это что-то вроде взлома, но пока это работает ...источник
'your_keys_name'
и'your_meta_key'
оба должны быть одной и той же строкой, а не отличаться друг от друга, иначе похоже, что вы неправильно поняли вопрос. Во-вторых, я проверил это на своей локальной установке, и он исключает все посты, где существует ключ (черезmeta_query
), и исключает любые посты, где ключ отсутствует (черезmeta_key
), в результате чего посты не отображаются. Тем не менее, этот ответ является шагом к чему-то, что слова, по крайней мере ;-).'relation' => 'OR'
кmeta_query
. Дурацкие штучки о_о.Я думаю, что @kaiser пытался сделать так, чтобы запрос возвращал все посты, которые имеют этот мета-ключ, применяя своего рода фиктивное условие условия, чтобы не фильтровать ни одну из этих постов. Поэтому, если вы знаете, что все значения, которые могут принимать ваши настраиваемые поля, это x, y, z, вы можете сказать «ГДЕ meta_key IN (x, y, z) », но идея в том, что вы можете избежать этой проблемы все вместе, сказав ! = (' ') :
Также не проверено, но кажется, что стоит попробовать :-).
источник
Я закончил тем, что обошел это с небольшим количеством взлома (IMHO), но это сделало работу для меня в моем случае.
Вы можете подключиться к фильтрам posts_join_paged и posts_orderby, чтобы обновить строки объединения и заказа. Это позволит вам делать заказы по вашему желанию, если вы сначала присоединитесь к нему, а не к WP_Query, предполагая, что поле должно существовать для этого конкретного сообщения. Затем вы можете удалить
meta_key
,orderby
и `заказ от ваших аргументов WP_Query.Ниже приведен пример. В верхней части каждой функции мне приходилось выходить из системы в определенных случаях, так как она добавит это ко всему, что использует WP_Query. Возможно, вам придется изменить это, чтобы соответствовать вашим конкретным потребностям.
К сожалению, документации по этим двум фильтрам не хватает, так что ... удачи! :)
источник
cast(my_custom_meta_key.meta_value as unsigned) DESC
должен сделать трюк ...$orderby_statement = "cast(my_custom_meta_key.meta_value as unsigned) DESC";
работает отлично.Это решение сработало для меня:
Однако это решение сначала показывает записи с нулевым meta_value. Это другое решение показывает порядок ASC и нули в конце:
источник