1

I'm trying to do a single WP_Query to get the posts that are in 2 different custom post types but the second post type has to be from a specific taxonomy.

This is what I'm currently doing:

    $query1 = new WP_Query(array(
    'numberposts'       => $postsnumber,
    'posts_per_page'   => $postsnumber,
    'orderby'          => 'publish_date',
    'order'            => 'DESC',
    'post_type'        => 'post',
    'post_status'      => 'publish',
    'suppress_filters' => false
));
$query2 = new WP_Query(array(
    'numberposts'       => $postsnumber,
    'posts_per_page'   => $postsnumber,
    'orderby'          => 'publish_date',
    'order'            => 'DESC',
    'post_type'        => 'js_videos',
    'tax_query' => array(
        array (
            'taxonomy' => 'video_category',
            'field' => 'tag_ID',
            'terms' => '41',
        )
    ),
    'post_status'      => 'publish',
    'suppress_filters' => false
));

$wp_query = null;
$wp_query = new WP_Query();
$wp_query->posts = array_merge( $query1->posts, $query2->posts );

However I need to still order by publish_date after mergining.

2 Answers 2

0

I'm going to take the answer you posted for yourself and suggest a couple of improvements.

Some things I'll address:

  • The 3rd query is unnecessary. There are simpler ways to sort by date. Just make both queries for the full post content and merge the results.
  • Since we're not going to be using have_posts() and the_post() (we'll use setup_postdata()), we should just use get_posts() to keep things a bit simpler. It should also be a bit quicker as it sets some default query args to optimise it since it won't need pagination info.
  • We'll avoid repeating ourselves with the query arguments by re-using a single array of arguments.
  • We won't bother specifying arguments that are just the defaults.

Taking those points into account, the code can just be:

$posts_args = [
    'posts_per_page' => $postsnumber,
    'post_type'      => 'post',
];

$posts = get_posts( $posts_args );

$video_args              = $posts_args;
$video_args['post_type'] = 'js_videos';
$video_args['tax_query'] =  [
    [
        'taxonomy' => 'video_category',
        'field'    => 'tag_ID',
        'terms'    => '41',
    ],
];

$videos = get_posts( $video_args );

$combined = array_merge( $posts, $videos );

usort( 
    $combined, 
    function( $a, $b ) {
        return get_post_time( 'U', false, $b ) - get_post_time( 'U', false, $a );
    }
);

global $post;

foreach ( $combined as $post ) : setup_postdata( $post );
    the_title(); // etc.
endforeach;

wp_reset_postdata();
0
0

Never mind.

I got it resolved doing it like this:

    $query1 = new WP_Query(array(
    'fields'            => 'ids',
    'numberposts'       => $postsnumber,
    'posts_per_page'   => $postsnumber,
    'orderby'          => 'publish_date',
    'order'            => 'DESC',
    'post_type'        => 'post',
    'post_status'      => 'publish',
    'suppress_filters' => false
));
$query2 = new WP_Query(array(
    'fields'            => 'ids',
    'numberposts'       => $postsnumber,
    'posts_per_page'   => $postsnumber,
    'orderby'          => 'publish_date',
    'order'            => 'DESC',
    'post_type'        => 'js_videos',
    'tax_query' => array(
        array (
            'taxonomy' => 'video_category',
            'field' => 'tag_ID',
            'terms' => '41',
        )
    ),
    'post_status'      => 'publish',
    'suppress_filters' => false
));

$post_ids = array_merge( $query1->posts, $query2->posts);

$args = array(
    'numberposts'      => $postsnumber,
    'posts_per_page'   => $postsnumber,
    'post__in'         => $post_ids, 
    'post_type'        => 'any',
    'orderby'          => 'publish_date', 
    'order'            => 'DESC',
); 

$wp_query = null;
$wp_query = new WP_Query();
$wp_query->query($args);
3
  • First of all... You're doing 3 queries not one. Your code will cause 3 DB queries, so they are 3 different queries and all you do is you merge their results. And leaving that aside... What's the point in $wp_query = null; $wp_query = new WP_Query(); - why do you assign null just to overwrite it one moment later? Jan 30, 2019 at 12:01
  • Thanks for the feedback. I'm overwriting a shortcode so I left that null assignment cause even though it didnt make sense cause I thought the original dev may know something that I dont. I'm still not sure around doing it in a single query and I've amended the array_merge to only do the posts. Jan 30, 2019 at 12:04
  • Your solution is correct - the only thing I have problem with is that it's not one query and I think that is worth noticing. The part with null is just some rubbish PHP myth that came from ThemeForest, I guess, and is repeated without any thought. It completely makes no sense, so just remove it. If you used any IDE, it would be marked as potential error. Jan 30, 2019 at 12:06

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.