27

I am running a multisite network and i have setup a sql query that uses swith_to_blog(); and queries the posts.

Is there a way that i can declare the query inside a new WP_Query and actually merge that query with another?

Basically if i do this:

$number1 = new WP_Query($multisitequery);

Can i merge it with:

$number2 = new WP_Query($normalquery);

$normalquery holds settings like pagination, per page, excerpt, title etc... on a portfolio shortcode.

I would like it to include queried posts from my new $multisite query.

Can this be achieved? Just wanting to save me from creating a whole new shortcode setup lol

Many thanks in advance. Rory

EDIT========

What i have is:

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

Further down my portfolio function "after all the $settings['options']" i have:

$portfolio_query = new WP_Query( $portfolio );

the $portfolio_query uses a loop on a page template.

I want to add an extra query into this like so:

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();
}

where i assume that $globalcontainer would be the array to merge into the wp_query();.

So taking onboard what you have replied with, in theory i could simply:

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

Would that be correct?

Second, regarding the array_merge array key overwrite..... How would i go about stopping an overwrite?

4 Answers 4

45

You won't do much good just merging the arguments, you need to merge the resulting posts array and the post_count count. This works for me:

//setup your queries as you already do
$query1 = new WP_Query($args_for_query1);
$query2 = new WP_Query($args_for_query2);

//create new empty query and populate it with the other two
$wp_query = new WP_Query();
$wp_query->posts = array_merge( $query1->posts, $query2->posts );

//populate post_count count for the loop to work correctly
$wp_query->post_count = $query1->post_count + $query2->post_count;
8
  • This looks good, but I am looking for a solution that can be used with the pre_get_posts hook - i.e., I need to modify an existing WP_Query object. I have tried using '$wp_query->init();' instead of '$wp_query = new WP_Query();', but that seems to mess things up. Any suggestions? Commented Dec 30, 2013 at 22:14
  • 1
    You should add a different question since it's a different answer, but you can use this same code but only the query2 parts, modifying the ->posts and ->post_count parts of the $wp_query object to have the sum of the original query that pre_get_posts gives you and the second query you want to append.
    – guidod
    Commented Jan 3, 2014 at 15:32
  • 2
    How can I remove duplicates from this merged array?
    – roshan
    Commented Nov 5, 2015 at 8:02
  • Thanks for this. Had a problematic meta_query using an OR relation. Split it up using this technique and went from 41s to 0.01s. Commented May 8, 2016 at 21:48
  • @ban-geoengineering Have you ever figured this out? I am stuck with this as well.
    – harvey
    Commented Oct 28, 2019 at 18:25
32

I generally merge their ID arrays and make a third query. To keep first set of queries cheap I only return their ID's using fields parameter like this:

//setup your queries with extra parameter fields => ids
$query1 = new WP_Query(array('fields' => 'ids','other_parameters' => 'etc'));
$query2 = new WP_Query(array('fields' => 'ids','other_parameters'=>'etc'));

//now you got post IDs in $query->posts
$allTheIDs = array_merge($query1->posts,$query2->posts);

//new query, using post__in parameter
$finalQuery = new WP_Query(array('post__in' => $allTheIDs));

Hope this helps

---EDIT---

After my answer original question is edited for multisite details. In case of multisite post merges this does not work.

6
  • 2
    This answer works well and feels like less of a hack than the top solution. Used it a year or so ago and came back to use it again now. Thank you.
    – Davey
    Commented Jul 5, 2017 at 11:01
  • How can this work properly when post_ID's are not unique on the multisite scope (they are unique per blog but several posts can have the same ID's across the network)?
    – Adal
    Commented Oct 5, 2017 at 21:41
  • 1
    @Adal Original question is edited after my answer so my answer is relevant for single site scope. with multisite I never tried to merge queries and in that case of course this won't work, queries need to be separately made and merged. After merge you can try ordering them with php sorting functions maybe (sort for publish date etc). Commented Oct 6, 2017 at 12:20
  • 6
    You can preserve the sorting by using 'orderby' => 'post__in' in the last query.
    – fregante
    Commented Feb 23, 2018 at 10:00
  • 3
    for custom post types, I think, post_type param need that in any case, even with asking by ids because it is post_type=post by default @RobbTe Commented Jan 15, 2019 at 17:03
4

So, if you have this:

$number1 = new WP_Query($multisitequery);

$number2 = new WP_Query($normalquery);

I assume you define these somewhere previous?

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

...in which case, to merge the two queries, just array_merge() the two arrays before passing them to new WP_Query():

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

$merged_query = new WP_Query( $merged_query_args );

Note that order is important in the array_merge() call. If both have the same array key, the second array will overwrite the first array.

1
  • Thank you for replying Chip, much appreciated. I have edited my original question to give you a better idea of what i have to work with. Many thanks indeed and i look forward to another knowledge packed reply lol Thanks Commented Jun 17, 2012 at 22:17
1

Thus, you can glue two WP_Query queries with different post_type or other sorting data, for example, and then glue them by ids into one WP_Query query that will fully work - in order to preserve the sorting when gluing, you need to specify orderby => post__in

my example is how it creates a new WP_Query cycle and can affect any other cycle for displaying posts by calling new global_change_of_sorting_posts->change_query_posts() => query_posts() you need to call before processing the cycle for displaying 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;
        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(),
            'orderby' => 'post__in',
        ]);
        while ($wp_query->have_posts()) {
            $wp_query->the_post();

            var_dump(get_the_ID());
        }
    }

    public function change_query_posts($query_string)
    {
        parse_str($query_string, $args);
        $args['post__in'] = $this->get_posts_ids();
        $args['orderby'] = 'post__in';
        query_posts($args); # query conversion
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.