How to get posts from multiple custom post types according to it’s custom taxonomy terms?

Your best solution here would be to run a single query where you will query

  • all post types

  • and all post from regardless of taxonomy

Once you have all that, you can then use usort() to sort your results accordingly. I do not know how you would want your post types sorted, but lets assume you want to sort by post type and term

OK, so lets look at the code, but before we do, lets look at some important notes

IMPORTANT NOTES TO CONSIDER

  • The following code is untested, so it might be buggy. It is adviceble to run this locally first with debug turned on

  • The code requires at least PHP5.4 and cause fatal errors on older versions due to short array syntax and direct array dereferecing. If you are still using using older versions, it is recommended that you upgrade. All versions before PHP5.4 have been EOL’ed, which holds huge security risk to your site if you are still using these versions

  • VERY VERY IMPORTANT: The sorting function in usort() will only work as expected if you have one or two post types in your query, if you have more than two post types, the logic in the function will not work properly. Also the logic will also just work as expected if each post type have one taxonomy assigned to it. Furthermore, if any post has more than one term assigned to it, only the first term will be used for sorting purposes

  • I will explain the code as I go along in the code itself to make it easy to understand

THE CODE

// Define our query arguments
$args = [
    'post_type' => ['dramas', 'reality_shows'], // Get posts from these two post types
    // Define any additional arguments here, but do not add taxonomy parameters
];
$q = new WP_Query( $args );

/**
 * We now need to sort the returned array of posts stored in $q->posts, we will use usort()
 *
 * There is a bug in usort causing the following error:
 * usort(): Array was modified by the user comparison function
 * @see https://bugs.php.net/bug.php?id=50688
 * This bug has yet to be fixed, when, no one knows. The only workaround is to suppress the error reporting
 * by using the @ sign before usort
 *
 * UPDATE FROM COMMENTS FROM @ birgire
 * The usort bug has been fixed in PHP 7, yeah!!
 */
@usort( $q->posts, function ( $a, $b )
{
    // Sort by post type if two posts being compared does not share the same post type
    if ( $a->post_type != $b->post_type )
        return strcasecmp( $a->post_type, $b->post_type ); // Swop the two variable around for desc sorting

    /**
     * I we reach this point, it means the two posts being compared has the same post type
     * We will now sort by taxonomy terms

     * The logic for the code directly below is, we have two post types, and a single post can only be assigned to 
     * one post type, so a post can only be from the dramas post type or from the reality_shows post type. We also just
     * need to check one of the two posts being compared as we know both posts are from the same post type. If they
     * they were not, we would not have been here
     *
     * The socond part of the logic is that the drama_taxonomy is only assigned to the dramas post type and the 
     * reality_shows_taxonomy is only assigned to the reality_shows post type, so we can set the taxonomy according
     * to post type
     */
    $taxonomy = ( $a->post_type == 'dramas' ) ? 'drama_taxonomy' : 'reality_shows_taxonomy';
    $terms_a = get_the_terms( $a->ID, $taxonomy );
    $array_a = ( $terms_a && !is_wp_error( $terms_a ) ) ? $terms_a[0]->name : 'zzzzz'; // zzzz is some crappy fallback

    $terms_b = get_the_terms( $b->ID, $taxonomy );
    $array_b = ( $terms_b && !is_wp_error( $terms_b ) ) ? $terms_b[0]->name : 'zzzzz'; // zzzz is some crappy fallback

    // We will now sort by terms, if the terms are the same between two posts being compared, sort by date
    if ( $array_a != $array_b ) {
        return strcasecmp( $array_a, $array_b ); // Swop the two variables around to swop sorting order
    } else {
        return $a->post_date < $b->post_date; // Change < to > to swop sorting order around
    }
}, 10, 2 );

// $q->posts is now reordered and sorted by post type and by term, simply run our loop now

Your loop should the look something like this. You will need to modify this to suit your exact needs

if ( $q->have_posts() ) {
    // Define variable to hold previous post term name
    $term_string = '';
    while ( $q->have_posts() ) {
    $q->the_post();

       // Set the taxonomy according to post type
      $taxonomy = ( 'reality_shows' == get_post_type() ) ? 'reality_shows_taxonomy' : 'drama_taxonomy';
        // Get the post terms. Use the first term's name
        $terms = get_the_terms( get_the_ID, $taxonomy );
      $term_name = ( $terms && !is_wp_error( $terms ) ) ? $terms[0]->name : 'Not assigned';
        // Display the taxonomy name if previous and current post term name don't match
        if ( $term_string != $term_name )
            echo '<h2>' . $term_name . '</h2>'; // Add styling and tags to suite your needs

        // Update the $term_string variable
        $term_string = $term_name;

        // REST OF YOUR LOOP

    }
 wp_reset_postdata();
}