Intereting Posts
Использование темы _s, изменения меню не влияют на меню заголовка Карты Google с категориями Почему я не могу получить доступ к моей интрасети LDAPS с помощью NADI? Создание пользовательских страниц панели администратора без создания плагина? Две петли на странице архива Изображения, отображаемые в редакторе, но не в записи Правильно ли я получил это утверждение IF? Разработка темы: лицензионная помощь Как обновить измененные плагины? Разная структура константы для каждой категории Отобразить ссылку на редактирование, если автор сообщения является текущим пользователем Кто это работает, чтобы загрузить переведенные строки плагина? Перемещение двух независимых сайтов в сеть Если я переименую плагин (в его основном файле php), все равно получаю уведомления об обновлениях? Автоматическое добавление последнего сообщения в карусель / слайдер

Комплексный мета-запрос с 3 ключами

Я думаю, что проблема в основном связана с sql-структурой запроса, и я не эксперт ….

Мне нужно искать сообщения (пользовательский тип сообщения) по двум параметрам:

  1. pd_city

  2. pd_country

Обратите внимание, что отношение meta_query равно «OR», поэтому, если любой из двух вышеперечисленных символов LIKE, мы должны иметь некоторые результаты.

Третий ключ (is_sponsored) используется для сортировки сообщений! Это может быть 1 или 0, а записи, значения которых «is_sponsored» равны 1, должны быть указаны сверху.

Итак, вот что говорит WordPress:

$sfp_query_args = array( 'sfp_complex_search' => 'yeap', 'tax_query' => array( array( 'taxonomy' => 'sfp_post_category', 'terms' => $term_id ) ), //'meta_key' => 'is_sponsored', 'post_type' => 'sfpposts', 'post_status' => 'publish', 'showposts' => (int)$per_page, 'paged' => $paged, 'meta_query' => array( 'relation' => 'OR', array( 'key' => 'pd_city', 'value' => $sfp_search_meta, 'compare' => 'LIKE' ), array( 'key' => 'pd_country', 'value' => $sfp_search_meta, 'compare' => 'LIKE' ), array( 'key' => 'is_sponsored' ) ) ); $sfp_search = new WP_Query( $sfp_query_args ); 

Мне также нужно фильтровать результаты с помощью «posts_orderby», чтобы привлечь спонсоров:

 add_filter( 'posts_orderby', 'sfp_modify_search' ); function sfp_modify_search( $orderby ) { if( !is_admin() && is_page( $this->options[ 'sfp_page_entries_search' ] ) ) { global $wpdb; $orderby = " CASE WHEN mt2.meta_value = 0 THEN 1 END, $wpdb->posts.post_date DESC "; } return $orderby; } 

Реальная проблема заключается в том, что с этим запросом возвращаются ВСЕ POSTS из «sfp_post_category», а не только те, которые соответствуют «pd_city» или «pd_country», потому что ВСЕ POSTS ИМЕЛИ «metal key is_sponsored» (и значение установлено в 1 или 0). Еще раз: «is_sponsored» необходим для сортировки!

Когда var_dump

 var_dump( $sfp_search->request ); 

… WordPress 'sql выглядит так:

 SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (77) ) AND wp_posts.post_type = 'sfpposts' AND (wp_posts.post_status = 'publish') AND ( (wp_postmeta.meta_key = 'pd_city' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%something%') OR (mt1.meta_key = 'pd_country' AND CAST(mt1.meta_value AS CHAR) LIKE '%something%') OR mt2.meta_key = 'is_sponsored' ) GROUP BY wp_posts.ID ORDER BY CASE WHEN mt2.meta_value = 0 THEN 1 END, wp_posts.post_date DESC LIMIT 0, 10 

Как удалить все сообщения, которые не соответствуют «pd_city» или «pd_country» из результатов?

Виновник

Суть дела – мета-запросы, не поддерживающие разные и / или вложенные отношения, – недостаток, кстати, это и привело меня в бешенство. В недавнем примере также есть сценарий поиска.

То, что вы хотите сделать просто, не может быть выполнено с помощью WP_Query а также одного цикла.
Как вы, кажется, заметили, размещаете ли вы ключ сортировки в массиве meta_query или вне его, поскольку общий аргумент запроса не имеет значения. Если вы установите отношение мета-запроса к OR и укажите meta_key любом месте запросов args без установки сопровождающего параметра meta_value , запрос всегда будет возвращать хотя бы все сообщения, где установлена ​​эта мета-клавиша.
Кстати и ради полноты: когда вы используете один meta_query с != Как значение для meta_compare , запрос возвращает все результаты с meta_key набора meta_key а не равным заданному meta_value – он не будет возвращать какие-либо сообщения, которые вообще не используется meta_key . Другой момент, когда мета-запросы терпят неудачу.

Решение 1

Я вижу два варианта. Во- is_sponsored , вы можете опустить мета-ключ is_sponsored из запроса, также опустить разбивку на страницы, получить правильные сообщения и выполнить сортировку со вторым экземпляром WP_Query , передав ему отфильтрованные идентификаторы сообщений через параметр post__in :

 $sfp_search_args = array( 'sfp_complex_search' => 'yeap', 'tax_query' => array( array( 'taxonomy' => 'sfp_post_category', 'terms' => $term_id ) ), 'post_type' => 'sfpposts', 'post_status' => 'publish', 'meta_query' => array( 'relation' => 'OR', array( 'key' => 'pd_city', 'value' => $sfp_search_meta, 'compare' => 'LIKE' ), array( 'key' => 'pd_country', 'value' => $sfp_search_meta, 'compare' => 'LIKE' ) ) ); $sfp_search = new WP_Query( $sfp_search_args ); $post_ids = array(); while ( $sfp_search->have_posts() ) : $sfp_search->next_post(); $post_ids[] = $sfp_search->post->ID; endwhile; $sfp_ordered_args( 'post__in' => $post_ids, // note that 'showposts' is deprected 'posts_per_page' => (int)$per_page, 'paged' => $paged, 'meta_key' => 'is_sponsored', 'order' => 'DESC', 'orderby' => 'meta_value_num date' ); $sfp_ordered = new WP_Query( $sfp_ordered_args ); while ( $sfp_ordered->have_posts() ) : $sfp_ordered->next_post(); // display posts endwhile; 

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

Решение 2

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

Если вы слегка изменили данный SQL, заменив логический оператор OR mt2.meta_key = 'is_sponsored' на AND и соответствующим образом переместив его, вы могли бы потянуть сообщения с помощью $wpdb :

 $sfp_post_ids = $wpdb->get_col( " SELECT wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) INNER JOIN wp_postmeta ON (wp_posts.ID = wp_postmeta.post_id) INNER JOIN wp_postmeta AS mt1 ON (wp_posts.ID = mt1.post_id) INNER JOIN wp_postmeta AS mt2 ON (wp_posts.ID = mt2.post_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id = $term_id ) AND wp_posts.post_type = 'sfpposts' AND (wp_posts.post_status = 'publish') AND ( (wp_postmeta.meta_key = 'pd_city' AND CAST(wp_postmeta.meta_value AS CHAR) LIKE '%$sfp_search_meta%') OR (mt1.meta_key = 'pd_country' AND CAST(mt1.meta_value AS CHAR) LIKE '%$sfp_search_meta%') ) AND mt2.meta_key = 'is_sponsored' GROUP BY wp_posts.ID ORDER BY CASE WHEN mt2.meta_value = 0 THEN 1 END, wp_posts.post_date DESC " ); 

На этом этапе у вас есть два варианта:
Или итерации по массиву $sfp_post_ids с простым foreach и вытащить данные post с помощью get_post() индивидуально в этом цикле или, если вы хотите получить тонкости WP_Query – подкачки, теги шаблонов и т. Д. – $sfp_post_ids post__in параметру post__in как в решении 1.

Это сложно 🙂

Я собирался предположить, что вам может не понадобиться array( 'key' => 'is_sponsored' ) в массиве «meta_query», и вы можете сделать это, добавив «meta_key» в основной массив, но он выглядит как вы это пробовали. Получали ли вы те же результаты?

JOIN s может усложнить ситуацию. Вы подключились к posts_orderby . Вы считали, что подключаетесь к posts_fields и добавляете подзапрос, который доставит вам ваше meta_value?

(SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = 'is_sponsored' AND post_id = {$wpdb->posts}.ID) as is_sponsored

Все это происходит из-за отношения OR к meta_query и того, как WordPress генерирует фактическую строку запроса. Я в конечном итоге подключился к фильтру posts_clauses чтобы изменить where и orderby фрагменты запроса:

 public function wpse_68002_orderby_fix($pieces){ global $wpdb; $pieces['where'] .= " AND $wpdb->postmeta.meta_key = 'your_meta_key'"; // <--- update here with your meta_key name $pieces['orderby'] = "$wpdb->postmeta.meta_value ASC"; return $pieces; } 

Просто добавьте фильтр перед настройкой объекта WP_Query, а затем обязательно удалите его после запуска запроса, чтобы не влиять на другие запросы:

  add_filter( 'posts_clauses', 'wpse_68002_orderby_fix', 20, 1 ); $query = new WP_Query($args); $result = $query->get_posts(); remove_filter( 'posts_clauses', 'wpse_68002_orderby_fix', 20 ); 

Не забудьте оставить meta_key и meta_key из аргументов запроса.