This post will cover a complex WordPress query and nested loop to output custom posts organized by a custom taxonomy. Let’s run through the specifics of this particular example. In the example, we’ll be organizing posts for our “Movie” post type by the years they were created, which is a custom taxonomy called “movie years”.
- Create a custom post type with a name of movie.
- Create a custom taxonomy for the movies post type and call it movie_years.
- Create a custom archive template for the movie post type.
- Retrieve every available year that contains a movie post.
- Loop through every year and output a separate section for each.
- Create a new WP_Query instance to pull posts from each year.
- Loop through each year’s query to output the appropriate posts, organized by ascending title.
Before starting, I’ll be using the Genesis Framework so my code will be specific for Genesis. However, the loops and queries are universal and can be used in any WordPress theme. By the time we’re finished, the archive page will look something like this:
Create the Movie Custom Post Type and Custom Taxonomy
I’m going to assume you’ve either registered the movie post type and taxonomy or are comfortable with doing so. If you haven’t yet registered them, here’s a snippet you can use to get going right away. It includes the code to register both the movie custom post type and its movie_years taxonomy.
Create the Movie Archive Template
Since I’m using Genesis, I could just include a conditional in the following code and place it in my functions.php but, because I like to keep my functions file as lean as possible, I always prefer a separate template file so, for this tutorial, create a file called archive-movie.php and save it in your child theme’s root directory. Next, copy and paste this code to the file:
This file completes steps 4-7 and finishes off the basic requirements for our movie post type archive page. I’ve commented the code for additional help but feel free to ask if you have any questions.
Amber @ Au Coeur says
Thanks for this tutorial! With a few modifications, it was just what I needed!
Ren says
Glad it helped!
Vajrasar says
Why did you use implode( ‘ ‘, get_post_class( $classes ) ) instead of just $classes?
Ren says
Hi, Vajrasar. Good question. Using
get_post_class( $classes )
adds the $classes variable to the default post classes and using it inimplode( ' ', get_post_class( $classes ) )
adds a space between all of the classes. The implode() function I don’t believe is necessary if the proper spacing is added to the $classes values but I used it to make sure. However, if you use $classes without get_post_class(), the regular post classes will not be added and the only classes it will have will be the ones you define in $classes. For testing, inspect the element to see the difference.Hopefully that helps.
Paal Joachim Romdahl says
Hey Ren
Thank you for your reply. I switched over to 6 column layout and adjusted the query and css to reflect this layout, but no change.
This is what I am looking at doing:
– Sort thumbnails by when the post was created. This way I can control the order. As the title will have a date and title of the movie. Sorting by post creation date will give me more control.
– I am getting one nice row, but the second row of the same year is having a problem showing up as it should even though I use the 6 column layout it is still not working.
Could you add on to your tutorial creating a second row in the same year and see how that goes?
Thanks Ren.
Paal Joachim
Paal Joachim Romdahl says
Hey Ren
This is awesome!
I am working on the film club site and adding movies.
The HTML site: http://spirituellfilm.no/filmer/filmarkiv.html
Each year we screen about 10 movies (or less). I then need 5 images to show on each row for the specific year.
Two questions:
How to get them in the order I want?
How do I get all the 10 movies – five in each row to show up? Right now 6 are showing up the rest are just not there.
I made a blog article to show you what is going on:
http://easywebdesigntutorials.com/creating-a-movie-custom-post-type/
Thanks Ren! Its very cool that we are making a good looking movie archive page. A down the road thought…I am thinking that we can also transfer the code over to show how something like this can be done in a regular category page template. As it would create a very cool blog and category page as well.
Have a great day!
Ren says
Hi, Paal. Sorry about the delay on this. To answer your questions, you should be able to just modify the query and CSS. I used the default columns that come with Genesis and there isn’t a five column layout so you’d need to add one by creating the CSS or using a different column number (you could do 4 or 6 with the default columns).
Adapting this code for other uses wouldn’t be too difficult and would just depend on what you’re trying to display.
Paal Joachim Romdahl says
Hey Ren
I am having a difficult time getting it to work properly. I have tried out a few variations and for whatever reason I am not able to get through this hurdle.
Having 9-10 movies January – May and the next row August – November
line up. If you could help that would be great.
Have a great weekend!
Ren says
Hi, Paal. Unfortunately, I don’t have a ton of free time to look at this in detail but, if you’d like to hire me to consult on it, you can send me the details here and I’ll get back with you on it.
Paal Joachim Romdahl says
Hey Ren
Thank you! I might just take you up on that.
I have one I do believe simple question.
How would I show name instead of slug?
As today is shows the year slug and not the year name.
I am finding a work around.
Since showing 10 movies from one year is not working.
As it shows 5 movies, and the next line a few blank spaces and then another movie. Meaning 6 movies. I tried changing the amount of columns, but was not successful in making a change.
I made a tag called year then spring and then year fall.
2015-spring and 2015-fall, and that is working.
I also am able to orderby date instead of slug.
$year_args = array(
‘post_type’ => ‘movie’,
‘orderby’ => ‘date’, /* CHANGED name -> date */
‘order’ => ‘DESC’, /* CHANGED ASC -> DESC */
‘tax_query’ => array(
array(
‘taxonomy’ => ‘movie_years’,
‘field’ => ‘slug’,
‘terms’ => $year,
),
),
The titles now have 2015-fall as it shows the slug. It would look nicer to have a 2015 Spring then a 2015 Fall showing the name.
Thanks Ren!
I look forward to down the road adding the code to a regular category archive view. As it is a really good way of showing an archive.
Paal Joachim Romdahl says
Another followup:
I changed the term to name as can be seen below:
//* Loop through each term and assemble an array of term slugs
foreach ( $terms as $term ) {
/* $years[] = $term->slug; -original code-*/
$years[] = $term->name;
}
Btw I had to change order back again to ASC (code added to the last post)
‘order’ => ‘ASC’, /* CHANGED ASC -> DESC -> CHANGED BACK again to ASC*/
It is now looking pretty good. I adjusted the tutorial I made based on your tutorial Ren: http://easywebdesigntutorials.com/creating-a-movie-custom-post-type/
Have a great day!
Ren says
Awesome! Glad to hear you got it working.