Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Taxonomy Archives: List Posts by Post Type

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

Final product image
What You'll Be Creating

In an earlier tutorial, I demonstrated how to create a taxonomy archive which lists posts by taxonomy term.

This tutorial is similar in that it shows you how to separate out posts in your archives, but it uses a different structure and a different template file. What I'll show you how to do here is to create an archive template for a taxonomy which lists posts by post type.

This might be useful if you have registered a post type which you want to keep separate from normal posts or from another post type, but have a taxonomy which applies to both. For example, if you're listing books and articles as different post types, but will have common topics as your taxonomy (e.g. WordPress!).

In the example I'll use here, I'll work with the 'animals' post type as I did in the previous tutorial, but this time I'll also be working with normal posts. I'll list animals with the queried term first and then I'll list blog posts with that term.

1. Getting Started: Creating the Theme

I'll create a theme which is a child theme of twentyfourteen, so if you're using the source files for this tutorial you'll also need that theme installed in your site. In my theme's stylesheet, I add the following:

/*
Theme Name:     WPTutsPlus Creating a Taxonomy Archive to List Posts by Post Type
Theme URI:      http://rachelmccollin.co.uk/wptutsplus-tax-archive-by-post-type/
Description:    Theme to support WPTutsPlus tutorial on creating a custom taxonomy archive. Child theme for the Twenty Fourteen theme.
Author:         Rachel McCollin
Author URI:     http://rachelmccollin.co.uk/
Template:       twentyfourteen
Version:        1.0
*/

@import url("../twentyfourteen/style.css");

That's all I need to add to create my child theme. If you're using your own theme, you can skip this step.

2. Registering the Post Type and Taxonomy

Note: If you followed my other tutorial about creating a custom post type archive template, you can use the theme you created for that as it uses the same post types and taxonomy. You'll just need to make one tweak which I'll highlight in this section, and add a new template file for the taxonomy archive.

The next step is to register the 'animal' post type and a 'animal family' taxonomy. Create a functions.php file for your theme and firstly add the function to register the post type:

// register a custom post type called 'animals'
function wptp_create_post_type() {
    $labels = array( 
		'name' => __( 'Animals' ),
		'singular_name' => __( 'animal' ),
		'add_new' => __( 'New animal' ),
		'add_new_item' => __( 'Add New animal' ),
		'edit_item' => __( 'Edit animal' ),
		'new_item' => __( 'New animal' ),
		'view_item' => __( 'View animal' ),
		'search_items' => __( 'Search animals' ),
		'not_found' =>  __( 'No animals Found' ),
		'not_found_in_trash' => __( 'No animals found in Trash' ),
	);
	$args = array(
		'labels' => $labels,
		'has_archive' => true,
		'public' => true,
		'hierarchical' => false,
		'supports' => array(
			'title', 
			'editor', 
			'excerpt', 
			'custom-fields', 
			'thumbnail',
			'page-attributes'
		),
		'taxonomies' => array( 'post_tag', 'category'), 
	);
	register_post_type( 'animal', $args );
} 
add_action( 'init', 'wptp_create_post_type' );

Next below that step, register the aminal family taxonomy.

If you're working with the theme created in the earlier tutorial, you'll need to add array('animal,'post') to your arguments for the function, intend of just 'animal'.

// register a taxonomy called 'Animal Family'
function wptp_register_taxonomy() {
    register_taxonomy( 'animal_cat', array( 'animal', 'post' ),
		array(
			'labels' => array(
				'name'              => 'Animal Families',
				'singular_name'     => 'Animal Family',
				'search_items'      => 'Search Animal Families',
				'all_items'         => 'All Animal Families',
				'edit_item'         => 'Edit Animal Families',
				'update_item'       => 'Update Animal Family',
				'add_new_item'      => 'Add New Animal Family',
				'new_item_name'     => 'New Animal Family Name',
				'menu_name'         => 'Animal Family',
			),
			'hierarchical' => true,
			'sort' => true,
			'args' => array( 'orderby' => 'term_order' ),
			'rewrite' => array( 'slug' => 'animal-family' ),
			'show_admin_column' => true
		)
	);
}
add_action( 'init', 'wptp_register_taxonomy' );

Save your functions file and you'll find your new post type and taxonomy appear in your site admin.

Now add some data - I've added some animals and posts to the 'Canines' family.

3. Creating the Archive Template

Now create a file called taxonomy-animal_cat.php. This will be the archive template for the new taxonomy.

Copy the wrapper code from your theme to this file so it has elements and classes in common with the rest of your theme. I'm copying from twentyfourteen - if you're using your own theme, copy from that. Copy everything except the heading and the loop, and add some comments at the top to remind you what this file is for:

<?php
/*
WpTutsPlus tutorial for creating archive to display posts by taxonomy term
Archive template for animal_cat taxonomy
*/
?>

<?php get_header(); ?>

<div id="main-content" class="main-content">

    <div id="primary" class="content-area">
		<div id="content" class="site-content" role="main">

			
			
		</div><!-- #content -->
	</div><!-- #primary -->
	<?php get_sidebar( 'content' ); ?>
</div><!-- #main-content -->

<?php
get_sidebar();
get_footer();

4. Identifying the Queried Object

So that you can display the name of the term being queried and define your queries in the two loops you'll be creating, you need to identify the queried object and save it as a variable.

Add the following somewhere near the top of your archive template (I'm adding it below the get_header() call):

<?php
// get the currently queried taxonomy term, for use later in the template file
$term = get_queried_object();
?>

You'll be using that in the next step.

5. Outputting the Archive Heading

Before adding your loops, you need to output a heading for your archive page. Inside the opening of the #content div, add the code below:

<header class="archive-header">
    <h1 class="archive-title">
		<?php echo $term->name; ?>
		<?php //post_type_archive_title(); ?>
	</h1>
</header><!-- .archive-header -->

6. The First Loop

Below the heading, you need to add your first loop, using WP_Query as you'll need to define the arguments. 

First define the query:

// Define the query
$args = array(
    'post_type' => 'animal',
	'animal_cat' => $term->slug
);
$query = new WP_Query( $args );

Note that this uses the$term variable you've already defined.

And then add the loop, outputting a link to each animal in an unordered list:

if ($query->have_posts()) {
    	
	// output the term name in a heading tag				
	echo'<h2>Animals in the ' . $term->name . ' Family</h2>';
	
	// output the post titles in a list
	echo '<ul>';
	
		// Start the Loop
		while ( $query->have_posts() ) : $query->the_post(); ?>

		<li class="animal-listing" id="post-<?php the_ID(); ?>">
			<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
		</li>
		
		<?php endwhile;
		
		echo '</ul>';
		
} // end of check for query having posts
	
// use reset postdata to restore orginal query
wp_reset_postdata();

?>

It's important to include two things here:

  • A check that the query has posts - you don't want to output a heading with no list beneath it.
  • wp_reset_postdata() to reset the query - you must always use this with WP_Query.

7. The Second Loop

The second loop is almost identical to the first loop except for the query arguments:

<?php //second query - posts

// Define the query
$args = array(
    'post_type' => 'post',
	'animal_cat' => $term->slug
);
$query = new WP_Query( $args );

if ($query->have_posts()) {

		
	// output the term name in a heading tag				
	echo'<h2>Blog Posts About the ' . $term->name . ' Family</h2>';
	
	// output the post titles in a list
	echo '<ul>';
	
		// Start the Loop
		while ( $query->have_posts() ) : $query->the_post(); ?>

		<li class="animal-listing" id="post-<?php the_ID(); ?>">
			<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
		</li>
		
		<?php endwhile;
		
		echo '</ul>';
		
} // end of check for query having posts
	
// use reset postdata to restore orginal query
wp_reset_postdata();

?>

Now save your template file and preview the archive. You should see two lists, one of animals and the other of posts:

Summary

That's how you create a taxonomy archive to list posts by post type. You could extend this technique to make your archive pages more interesting:

  • Varying the loops so that different content is output for each one, for example outputting a featured image or excerpt for some post types.
  • Adding different styling for each post type.
  • Changing the layout so the archives are side by side or in a grid. You can see and example of a site where I did this at http://type-academy.co.uk/temperament-intro/
  • Adapting this technique to category or tag archives by altering your query arguments.

I'm sure you can think of more possibilities!

Advertisement