Select All in Parent Category, Group by Child Category?

I am trying to format a custom post type for a “series”. Each post is an Episode, each Episode belongs to a Season, and each Season belongs to a series (just like a TV show).

I have the following:

  • Custom Post type: “Episodes”
  • Custom Taxonomy: “Series”
    • Inside Series, parent category of “Real Deal”
      • Inside “Real Deal” category, several subcategories (IE “Season 1”, “Season 2” ..)

I need to be able to select my “Episodes” both by Series (IE, “Real Deal” in the above), as well as by Season (IE, “Season 1” of Real Deal).

An image speaks a thousand words so here’s a quick mockup of what I mean:

enter image description here

WHAT I’VE TRIED

Here’s the code I currently have, however I don’t think I’m on the right track for doing what I’ve illustrated above. This will get me all the Episodes for Season 1, However I need to get all the episodes for every season, and then group each season into it’s own HTML container.

<?php
  $args = [
      'post-type'   => 'episode',
      'post-status' => 'publish',
      'tax_query'   => [
          [
              'taxonomy' => 'series',
              'field'    => 'slug',
              'terms'    => 'season-1'
          ]
      ]
  ];
  $episodes = new WP_Query($args);
  if ( $episodes->have_posts() ) {
    while( $episodes->have_posts() ) {
        $episodes->the_post();
        get_template_part('content','episodes');
    }
  } else {
    get_template_part('content', 'none');
  }
?>

QUESTION

How can I structure my Query to A) Select all episodes, grouped by Series, then displayed by season?

EDIT:

I ended up using the 3rd code snippet provded by Michael Ecklund, it managed to accomplish exactly what I was looking for — grabbing the 4 most recent posts in each season, and storing them into an array. Thank you for your help!

1
1

Here’s a straight up simple solution. Requires you to have the most recent version of WordPress though. (or at least 4.1)

Using nested taxonomy query.

Taking what you have, and just adding to it a bit.

$args = array(
    'post-type'      => 'episode',
    'post-status'    => 'publish',
    'posts_per_page' => 4,
    'tax_query'      => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'series',
            'field'    => 'slug',
            'terms'    => array( 'real-deal' ),// Name of the series (in slug format)
        ),
        array(
            'taxonomy' => 'series',
            'field'    => 'slug',
            'terms'    => array( 'season-1' ),// Name of the season (in slug format)
        )
    )
);

$episodes = new WP_Query( $args );

print_r( $episodes->posts );

That’s just saying find the 4 most recent published episodes that belong to a specific series and also contain a specific season. (this is what your visual mockups appear to be portraying)

You mentioned needing the “seasons” to be dynamic.

Here’s how you can get all “subcategories” (seasons) from the parent category (series) and then retrieve the 4 latest episodes from that series, and in all possible seasons.

$taxonomy = 'series';

$seasons = get_terms( $taxonomy, array(
    'parent' => 1, // TERM ID OF THE SERIES
    'fields' => 'id=>slug'
) );

if ( ! empty( $seasons ) && ! is_wp_error( $seasons ) ) {

    $args = array(
        'post-type'      => 'episode',
        'post-status'    => 'publish',
        'posts_per_page' => 4,
        'tax_query'      => array(
            'relation' => 'AND',
            array(
                'taxonomy' => $taxonomy,
                'field'    => 'slug',
                'terms'    => array( 'industry-news' ),// Name of the "series" (in slug format)
            ),
            array(
                'taxonomy' => $taxonomy,
                'field'    => 'slug',
                'terms'    => array_values( $seasons ),// Name of the "seasons" (in slug format) DYNAMIC
            )
        )
    );

    $episodes = new WP_Query( $args );

    print_r( $episodes->posts );

}

Let’s say you have 3 seasons in a series… And you want to display the 4 latest episodes from each season in this series.

$taxonomy = 'series';

$seasons = get_terms( $taxonomy, array(
    'parent' => 1, // TERM ID OF THE SERIES
    'fields' => 'id=>slug'
) );

$season_episodes = array();

if ( ! empty( $seasons ) && ! is_wp_error( $seasons ) ) {

    foreach ( array_values( $seasons ) as $season ) {

        $season_episodes[ $season ] = array();// Placeholder in-case there's no episodes found.

        $args = array(
            'post-type'      => 'episode',
            'post-status'    => 'publish',
            'posts_per_page' => 4,
            'tax_query'      => array(
                'relation' => 'AND',
                array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'slug',
                    'terms'    => array( 'industry-news' ),// Name of the "series" (in slug format)
                ),
                array(
                    'taxonomy' => $taxonomy,
                    'field'    => 'slug',
                    'terms'    => array( $season ),// Name of the "seasons" (in slug format) DYNAMIC
                )
            )
        );

        $episodes = new WP_Query( $args );

        if ( ! empty( $episodes->posts ) ) {
            $season_episodes[ $season ] = $episodes->posts;// Add all episodes found in this season.
        }

    }

}

if ( ! empty( $season_episodes ) ) {
    print_r( $season_episodes );
}

This last method will take the latest 4 episodes in a series put those 4 posts into separate arrays categorized by seasons.

So all said and done, you’ll have an array for each season in the series containing 4 recent episodes. All you have to do is output the information.

Leave a Comment