Please Note: This article has since been extended. Please read more up-to-date information in Revisiting Custom Post Types, Custom Taxonomies, and Permalinks
Note: This article is an extension of Custom Post Types, Custom Taxonomies, and Permalinks in WordPress 3.0 which discusses the Custom Post Type and Custom Taxonomy implementation we’ve setup thus far. While a summary is offered here, please know that some details discussed herein reflect the implementation discussed previously.
In order to set up front end visible archive pages for Custom Taxonomies, everything begins with the rewrite slug attached to your Custom Taxonomy. This can be edited using the Custom Rewrite Slug field provided by Custom Post Type UI. Some planning is required on your part, but the plan must take into consideration the Page structure currently implemented.
So far, we’ve based our Cameras Custom Post Type on the slug of
/cameras/. This works out well as our Custom Post Type houses information based on DSLR Cameras. We’ve set up an index-style page that sits at
/cameras/, and our single pages are stored under
/cameras/%postname%/. We’ve just now included a Custom Taxonomy, and we’d like to include that in the mix as well.
Out of the box taxonomy permalinks
By default, a Custom Taxonomy rewrite slug is based on the Taxonomy Name. Considering our Brands Custom Taxonomy, we might expect the Taxonomy listing would be made available at
/cameras/brands/%taxonomyname%/; unfortunately that’s not the case. Given the Taxonomy being a default implementation, we’d actually find the listing at
/brands/%taxonomyname%/. You’ll also note that any Cameras we’ve marked under a particular brand will show up in the listing. For example, if we navigated to
http://wordpress/cpt/brands/canon/, we’d be faced with a page resembling:
This listing behaves just like a regular Posts archive page would, and that’s because it’s literally based on the
archive.php template file of your theme. While it works, it’s not ideal. Thinking ahead, if you have multiple Custom Post Types along with WordPress posts, there isn’t much segmentation when it comes to actually viewing archive pages on the front end.
Take into consideration the possibility of us expanding our content by also including a Custom Post Type for Flashes. If we were to use a Custom Taxonomy for Flash Brands (as opposed to Camera Brands) with that Custom Post Type as well, we’d have overlapping entries and it would quickly become unorganized as results for both flashes and cameras would turn up when viewing
http://wordpress/cpt/brands/canon/ which isn’t always desirable.
At this point it’s important to note the specificity of a Custom Post Type/Custom Taxonomy implementation. There is a strong possibility that you very well may want to merge Canon flashes and cameras in your archive pages, but you may not. For the purpose of example, we’re going to deem it necessary to segment the two. To accomplish that, you’ll need to beef up the rewrite slug for your Custom Taxonomies.
Customizing your Custom Taxonomy template
When dealing with taxonomies, WordPress looks for specific theme files. As with other theme files, templates for Custom Taxonomies can be based on the taxonomy name, in this case
brands. Create a file called
taxonomy-brands.php in your theme directory, WordPress checks for this file before hitting
archive.php which can allow you to make the front end more custom. As an example, we’ll use the following for our
|<?php get_header(); ?>|
|<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); ?>|
|<div id="content" role="main">|
|<h1 class="page-title"><?php echo $term->name; ?> Archives</h1>|
|<?php if (have_posts()) : ?>|
|<?php while (have_posts()) : the_post(); ?>|
|<div class="post type-post hentry">|
|<a href="<?php echo get_permalink(); ?>" title="<?php the_title(); ?>" rel="bookmark">|
|<?php the_title(); ?>|
|<span class="meta-prep meta-prep-author">Posted on</span>|
|<a href="<?php echo get_permalink(); ?>" title="<?php the_time( 'g:i a' ); ?>" rel="bookmark">|
|<span class="entry-date"><?php the_time( 'F j, Y' ); ?></span></a>|
|</div><!-- .entry-meta -->|
|<?php the_excerpt(); ?>|
|</div><!-- .entry-summary -->|
|<?php endwhile; ?>|
|<?php endif; ?>|
|</div><!-- #content -->|
|</div><!-- #container -->|
|<?php get_sidebar(); ?>|
|<?php get_footer(); ?>|
This file is based on
category.php with a few modifications. First is the call to
get_term_by() which uses
get_query_var() to determine what Custom Taxonomy term we’re working with. From there, we carry on through The Loop as normal, outputting the information we’d like to use and where.
The only lasting problem here, is the fact that we’re still sitting at
http://wordpress/cpt/brands/canon/. I’d much rather have this page available at
http://wordpress/cpt/cameras/brands/canon/ as to differentiate it from other Custom Post Types and their Custom Taxonomies.
Correctly identifying your rewrite slug
Custom Post Type UI makes it really easy to modify our Custom Rewrite Slug, which controls this change entirely. As mentioned earlier, a rewrite slug, unless otherwise defined, is based on the Custom Taxonomy name itself, hence our current
/brands/%taxonomyname%/ result. We simply need to change our Custom Rewrite Slug to include the URL structure we’re looking for, in this case cameras/brands:
Saving the change to our Custom Taxonomy rewrite slug will push the permalink change and we’ll finally be able to hit our more appropriate
http://wordpress/cpt/cameras/brands/canon/ URL, right? Not quite. It turns out that if we hit
http://wordpress/cpt/cameras/brands/canon/ WordPress thinks we’re trying to hit a single post from our Cameras Custom Post Type and redirects us to the closest match.
In order to get our final archives-style pages to load properly, we’re going to have to modify our Custom Post Type Custom Rewrite Slug to differentiate a request for a single post entry versus our archive-style pages. To do that, we’ll need to change the slug from
cameras to something more appropriate like
cameras/body which could signify that we’re viewing a camera body.
With that change in place, we’re in business! We’re now able to hit
http://wordpress/cpt/cameras/brands/canon/ and view the Posts that have been marked as Canon Posts, using our custom permalink as well as our custom template file. You can repeat this process with additional taxonomies by creating appropriate rewrite slugs in conjunction with new
taxonomy-%taxonomyname%.php template files.
Adding links to Taxonomy archives in the sidebar
Many of the WordPress-native functions can be adapted for use with Custom Post Types and Custom Taxonomies. To add links to your newly created Custom Taxonomy archive pages, you could add something like this snippet to your
|<li id="camera-brands" class="widget-container">|
|<h3 class="widget-title">Camera Brands</h3>|
|<?php $cam_brands = get_terms('brands', 'hide_empty=1'); ?>|
|<?php foreach( $cam_brands as $brand ) : ?>|
|<a href="<?php echo get_term_link( $brand->slug, 'brands' ); ?>">|
|<?php echo $brand->name; ?>|
|$wpq = array( 'post_type' => 'cameras', 'taxonomy' => 'brands', 'term' => $brand->slug );|
|$brand_posts = new WP_Query ($wpq);|
|<?php foreach( $brand_posts->posts as $post ) : ?>|
|<a href="<?php echo get_permalink( $post->ID ); ?>">|
|<?php echo $post->post_title; ?>|
|<?php endforeach ?>|
|<?php endforeach ?>|
While a bit of the markup is specific to Twenty Ten’s
sidebar.php we can dissect what’s going on here:
- Pull our brands
- Create a list item for our brand
- Pull all posts that have been marked as being that brand (via the
- Loop through each post within that defined Custom Taxonomy entry and dump out what we’d like to use
- Repeat until finished with all Custom Taxonomy entries
When incorporated into the sidebar, we’ll get something like this:
As you can imagine, that sidebar listing would quickly grow to an unmanageable size, but the example illustrates just what’s possible using a few WordPress native functions and your Custom Post Types/Custom Taxonomies.
Custom Post Types and Custom Taxonomies are powerful
These changes in WordPress 3.0 are more than welcome, as they’re going to set the stage for much more traditional CMS-like behavior. The implementation discussed in this short series of articles is quite specific but hopefully outlines one of the many ways to work with Custom Post Types and Custom Taxonomies, all the while keeping a prettier permalink structure throughout your sites.