Можно ли объединить 2 запроса WP_Query($variable)?

17 июн. 2012 г., 13:53:15
Просмотры: 44K
Голосов: 27

Я использую мультисайт WordPress и настроил SQL-запрос, который использует switch_to_blog(); для запроса постов.

Есть ли способ объявить запрос внутри нового WP_Query и объединить его с другим запросом?

По сути, если я делаю это:

$number1 = new WP_Query($multisitequery);

Могу ли я объединить его с:

$number2 = new WP_Query($normalquery);

$normalquery содержит настройки пагинации, количества записей на странице, отрывков, заголовков и т.д. для шорткода портфолио.

Я хотел бы включить запрошенные посты из моего нового запроса $multisite.

Возможно ли это? Просто хочу избежать создания полностью новой настройки шорткода.

Заранее спасибо. Рори

РЕДАКТИРОВАНИЕ========

То, что у меня есть:

$portfolio = array();
$portfolio = $settings;

Далее в моей функции портфолио "после всех $settings['options']" у меня есть:

$portfolio_query = new WP_Query( $portfolio );

$portfolio_query использует цикл на шаблоне страницы.

Я хочу добавить дополнительный запрос следующим образом:

global $wpdb, $blog_id, $post;

// Получаем все блоги
$blogs = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM wp_blogs ORDER BY blog_id" ) );

$globalcontainer = array();

foreach ($blogs as $blog){
   // Переключаемся на блог
   switch_to_blog($blog->blog_id);

   $globalquery = query_posts($args);

   // Объединяем результаты
   $globalcontainer = array_merge( $globalcontainer, $globalquery );

   // Восстанавливаем текущий блог
   restore_current_blog();
}

где я предполагаю, что $globalcontainer будет массивом для объединения с wp_query();.

Итак, принимая во внимание то, что вы ответили, теоретически я мог бы просто:

$mergedqueryargs = array_merge($portfolio , $globalcontainer);
$portfolio_query = new WP_query($mergedqueryargs);

Это будет правильно?

Во-вторых, относительно перезаписи ключей массива при array_merge..... Как мне предотвратить перезапись?

0
Все ответы на вопрос 4
8
46

Просто объединения аргументов будет недостаточно, вам нужно объединить результирующий массив записей и счетчик post_count. Вот решение, которое работает у меня:

//настраиваем запросы, как вы уже делаете
$query1 = new WP_Query($args_for_query1);
$query2 = new WP_Query($args_for_query2);

//создаем новый пустой запрос и заполняем его двумя другими
$wp_query = new WP_Query();
$wp_query->posts = array_merge( $query1->posts, $query2->posts );

//устанавливаем правильное количество записей для корректной работы цикла
$wp_query->post_count = $query1->post_count + $query2->post_count;
13 нояб. 2013 г. 22:44:55
Комментарии

Это выглядит хорошо, но мне нужно решение, которое можно использовать с хуком pre_get_posts - то есть мне нужно модифицировать существующий объект WP_Query. Я пробовал использовать '$wp_query->init();' вместо '$wp_query = new WP_Query();', но это, кажется, всё портит. Есть предложения?

Boycott A.I. Boycott A.I.
31 дек. 2013 г. 00:14:13

Вам стоит задать отдельный вопрос, так как это другой ответ, но вы можете использовать этот же код, только части query2, модифицируя свойства ->posts и ->post_count объекта $wp_query, чтобы они содержали сумму оригинального запроса, который даёт вам pre_get_posts, и второго запроса, который вы хотите добавить.

guidod guidod
3 янв. 2014 г. 17:32:11

Как я могу удалить дубликаты из этого объединённого массива?

roshan roshan
5 нояб. 2015 г. 10:02:53

Спасибо за это. Были проблемы с meta_query, использующей отношение OR. Разделил запрос с помощью этой техники, и время выполнения сократилось с 41с до 0.01с.

Craig Harshbarger Craig Harshbarger
9 мая 2016 г. 00:48:59

@ban-geoengineering Ты смог разобраться с этим? У меня такая же проблема.

harvey harvey
28 окт. 2019 г. 20:25:31

@harvey Извини, не могу найти код, связанный с этим. (Это было несколько лет назад.) Лучше всего создать новый вопрос. Удачи. :-)

Boycott A.I. Boycott A.I.
28 окт. 2019 г. 23:46:43

Если вы создаете новый массив и удаляете дубликаты с помощью чего-то вроде array_unique(), вы можете заполнить $wp_query->post_count с помощью count($wp_query->posts)

armadadrive armadadrive
4 июн. 2020 г. 02:32:43

Кроме того, вам также нужно будет обновить "found_posts", например: $wp_query->found_posts = $promotor->found_posts + $other->found_posts;

Loosie94 Loosie94
26 нояб. 2020 г. 12:03:58
Показать остальные 3 комментариев
7
33

Обычно я объединяю их массивы ID и выполняю третий запрос. Чтобы первые запросы были дешевыми, я возвращаю только их ID, используя параметр fields, вот так:

//настраиваем запросы с дополнительным параметром fields => ids
$query1 = new WP_Query(array('fields' => 'ids','other_parameters' => 'etc'));
$query2 = new WP_Query(array('fields' => 'ids','other_parameters'=>'etc'));

//теперь у нас есть ID записей в $query->posts
$allTheIDs = array_merge($query1->posts,$query2->posts);

//новый запрос, используя параметр post__in
$finalQuery = new WP_Query(array('post__in' => $allTheIDs));

Надеюсь, это поможет

---ОБНОВЛЕНИЕ---

После моего ответа исходный вопрос был отредактирован с учетом деталей мультисайта. В случае слияния записей в мультисайте этот метод не работает.

30 июл. 2015 г. 20:19:43
Комментарии

Это решение работает хорошо и выглядит менее костыльным, чем топовый вариант. Использовал его около года назад и вернулся, чтобы снова применить. Спасибо.

Davey Davey
5 июл. 2017 г. 14:01:46

Как это может корректно работать, если post_ID не уникальны в рамках мультисайта (они уникальны в пределах блога, но несколько записей могут иметь одинаковые ID в сети)?

Adal Adal
6 окт. 2017 г. 00:41:11

@Adal Исходный вопрос был отредактирован после моего ответа, поэтому мой ответ актуален для одиночного сайта. С мультисайтом я никогда не пробовал объединять запросы, и в этом случае, конечно, это не сработает — запросы нужно выполнять отдельно и затем объединять. После объединения можно попробовать отсортировать их с помощью PHP-функций сортировки (например, по дате публикации).

Bora Yalcin Bora Yalcin
6 окт. 2017 г. 15:20:43

Вы можете сохранить сортировку, используя 'orderby' => 'post__in' в последнем запросе.

fregante fregante
23 февр. 2018 г. 12:00:25

Это работает для меня только при указании post_type в $finalQuery

RobbTe RobbTe
15 янв. 2019 г. 16:26:35

Для пользовательских типов записей, думаю, параметр post_type нужен в любом случае, даже при запросе по id, потому что по умолчанию post_type=post @RobbTe

Bora Yalcin Bora Yalcin
15 янв. 2019 г. 19:03:08

Убедитесь, что проверяете, не является ли массив объединенных ID пустым. Потому что запрос post__in возвращает результаты, если массив пуст. Это баг, который WP отказывается исправлять: https://core.trac.wordpress.org/ticket/28099

Sherri Sherri
25 мар. 2025 г. 16:05:45
Показать остальные 2 комментариев
1

Итак, если у вас есть такой код:

$number1 = new WP_Query($multisitequery);

$number2 = new WP_Query($normalquery);

Я предполагаю, что вы где-то ранее определяете эти переменные?

$multisitequery = array();
$normalquery = array();

...в таком случае, чтобы объединить два запроса, просто используйте array_merge() для слияния двух массивов перед передачей их в new WP_Query():

$merged_query_args = array_merge( $normalquery, $multisitequery );

$merged_query = new WP_Query( $merged_query_args );

Обратите внимание, что порядок аргументов в вызове array_merge() имеет значение. Если оба массива содержат одинаковые ключи, значения из второго массива перезапишут значения из первого.

17 июн. 2012 г. 21:57:06
Комментарии

Спасибо за ответ, Chip, очень признателен. Я отредактировал свой первоначальный вопрос, чтобы вам было понятнее, с чем мне приходится работать. Огромное спасибо и с нетерпением жду очередного насыщенного знаниями ответа, лол. Спасибо

Rory Rothon Rory Rothon
18 июн. 2012 г. 01:17:54
0

Таким образом, можно объединить два запроса WP_Query с разными post_type или другими параметрами сортировки, например, а затем склеить их по ids в один рабочий запрос WP_Query — чтобы сохранить сортировку при склейке, необходимо указать orderby => post__in

Мой пример показывает, как создается новый цикл WP_Query, который может влиять на любой другой цикл вывода записей путем вызова new global_change_of_sorting_posts->change_query_posts() => query_posts(). Этот вызов нужно выполнить до обработки цикла вывода записей!

class global_change_of_sorting_posts
{
    public function get_posts_ids()
    {
        $query1 = new WP_Query([
            'fields' => 'ids',
            'posts_per_page' => -1,
            'post_type' => 'post', // Стандартный тип записи
        ]);
        $query2 = new WP_Query([
            'posts_per_page' => -1,
            'fields' => 'ids',
            'post_type' => 'custom-post', // Пользовательский тип записи
        ]);
        $merge_ids_posts = $query1->posts + $query2->posts; // Объединение ID записей
        wp_reset_query();
        return $merge_ids_posts;
    }

    public function get_posts_wp_query()
    {
        $paged = (get_query_var('paged')) ? get_query_var('paged') : 1; // Получение текущей страницы пагинации
        $posts_per_page = 40;
        $wp_query = new WP_Query([
            'posts_per_page' => $posts_per_page,
            'paged' => $paged,
            'post__in' => $this->get_posts_ids(), // Используем объединенные ID
            'orderby' => 'post__in', // Сохраняем порядок сортировки
        ]);
        while ($wp_query->have_posts()) {
            $wp_query->the_post();

            var_dump(get_the_ID()); // Выводим ID текущей записи
        }
    }

    public function change_query_posts($query_string)
    {
        parse_str($query_string, $args); // Разбираем строку запроса
        $args['post__in'] = $this->get_posts_ids(); // Добавляем объединенные ID
        $args['orderby'] = 'post__in'; // Устанавливаем сортировку
        query_posts($args); // Модифицируем основной запрос
    }
}
16 июл. 2020 г. 11:04:32