3

I want to create a single array of posts by merging the results of 2 separate get_posts queries, and have the array ordered by published date.

In my code below, the get_posts for $args_b and $args_a have been merged into one array, but they are separated: The 9 titles of $args_b are listed first and then the 9 titles of $args_a. I want them to be mixed, and ordered by date. How do I sort them?

<?php
    $args_a = array(
    'posts_per_page' => 9,
    'category_name' => 'shinmatsudo',
    'category__in' => array( 227 ),
    'category__not_in' => array( 3 ),
    'meta_query' => array(
                          'relation' => 'AND',
                                              array(
                                                    'key'     => '1b',
                                                    'compare' => 'NOT EXISTS'
                                                     ),
    
                                               array(
                                                    'key'     => '1d',
                                                    'compare' => 'NOT EXISTS'
                                                     ),
                                                                
                          ), 
    );?>
    
    
    <?php
    $args_b = array(
    'category_name' => 'matsudo',
    'posts_per_page' => 9,
    'category__in' => array( 329 ),
    'category__not_in' => array( 3 ),
    'meta_query' => array(
                    'relation' => 'and',
                                    array(
                                    'key'=> '2a',
                                    'value' => array('2020-02-01' , '2020-06-01'),
                                    'compare' => 'BETWEEN',
                                    'type' => 'DATE',
                                    ),
                        ),
    );
    ?>
    
    
    <?php
    global $post;
    $my_posts= array_merge( get_posts($args_b), get_posts($args_a) );
    
    
    foreach($my_posts as $post):setup_postdata($post);?>

    <?php the_title(); ?>
        
    <?php endforeach; ?>
    <?php wp_reset_postdata(); ?>
FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
cwhiro
  • 105
  • 7
  • Thank you for editting my question. Sorry for my poor language skills. I will be careful next time. – cwhiro Jul 25 '20 at 21:00

1 Answers1

6

Merging the results of 2 separate queries won't change the order, so you will need to do a sort on them yourself.

Because because get_posts returns an array of objects, we need to use a sort function that lets you create a user-defined comparison (e.g. usort) - in other words we tell it what values to sort on and in what order.

If you are using PHP 7, you can use an anonymous function for the sort and the "spaceship operator" <=> to do the comparison, so this is all you need:

usort($my_posts, function($post_a, $post_b) {
    // Compare the post_date of the posts, and if $post_b is newer, then it will be displayed first
    return $post_b->post_date <=> $post_a->post_date;
});

(Note that normally you would use return $a->value <=> $b->value; to return the results in ascending order, but as we are working with dates and want the newest first, then we need to reverse the comparison to be return $b->value <=> $a->value;)

So in your code, you just need to use it like this:

<?php
// do your merge...
$my_posts= array_merge( get_posts($args_b), get_posts($args_a) );

// sort the resulting array...
usort($my_posts, function($post_a, $post_b) {
    return $post_b->post_date <=> $post_a->post_date;
});   

// and now process the new sorted array as required.    
foreach($my_posts as $post):setup_postdata($post);?>
    <?php the_title(); ?>
<?php endforeach; ?>
<?php wp_reset_postdata(); ?>

UPDATE: If you are still using PHP 5 (which you shouldn't be!), you can use the following instead:

usort($my_posts, function ($a, $b) {
    if ($a->post_date < $b->post_date)       return -1;
    elseif ($a->post_date > $b->post_date)   return 1;
    else                                     return 0;
});
FluffyKitten
  • 13,824
  • 10
  • 39
  • 52
  • Thank you so much ! I just tried by method of PHP7. It works completely as I expected ! Can I ask you one more thing? I use 'paged' => $paged usually in array for pagination. Now, where should I set it in this case? I set it to both $args_a and $args_b, but pagination does not appear. – cwhiro Jul 25 '20 at 20:51
  • 1
    Glad it worked! Setting up pagination on custom queries is a bit more complicated. That's a whole new question, but here are a few related SO questions: [Custom wp_query with working pagination](https://stackoverflow.com/questions/53437554/) & [paginate WP_Query results when there's an offset?](https://stackoverflow.com/questions/49227520/) or this page: [Use WP_Query to Create Pagination ](https://www.wpblog.com/use-wp_query-to-create-pagination/)... However I'm not sure how you'd do pagination with what you're doing because you are sorting the results *after* the query... that's a tough one! – FluffyKitten Jul 25 '20 at 21:04
  • @FluttyKitten Thank you for your reply. Thanks again for related links. – cwhiro Jul 26 '20 at 01:22
  • @FluttyKitten Its tough as you mentioned. No result in these hours. I give up to solve it by myself, and will make new question. – cwhiro Jul 26 '20 at 04:18