Custom CPT-onomy Archive Pages

As of version 1.2, CPT-onomies has implemented a simple, built-in method of setting up custom CPT-onomy archive pages that’s as easy as adding a rewrite rule with a few parameters. I’ve included a few samples that should help you get your feet wet.

Just a few notes before you get started:

  • The ‘cpt_onomy_archive=1’ parameter is required to make all of this work.
  • Keep in mind that the order in which you add your rewrite rules are important because rules with similar structure could overwrite one another. Rewrite URLs with longer structure usually need to be added first.
  • Be sure to flush your rewrite rules each time you edit them. Flush your rewrite rules by visiting Settings -> Permalinks and clicking “Save Changes”.
  • If you really want to keep track of your custom rewrites, and make sure everything is working just right, I highly recommend installing the Rewrite Rules Inspector plugin.

Add this code to your functions.php file:

<?php
add_action( 'init', 'my_website_add_rewrite_rule' );
function my_website_add_rewrite_rule() {

   /**
    * The following set of rewrite rules states that if the URL matches this rule,
    * i.e. http://mywebsite.com/movies/directors/steven-spielberg/, then the page
    * should display all post type 'movies' that are tagged with a specified term
    * from the 'directors' CPT-onomy
    */
   
   // if you want feeds
   add_rewrite_rule( 'movies/directors/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=movies&directors=$matches[1]&feed=$matches[2]&cpt_onomy_archive=1', 'top' );
   add_rewrite_rule( 'movies/directors/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=movies&directors=$matches[1]&feed=$matches[2]&cpt_onomy_archive=1', 'top' );

   // if you want pagination
   add_rewrite_rule( 'movies/directors/([^/]+)/page/?([0-9]{1,})/?$', 'index.php?post_type=movies&directors=$matches[1]&paged=$matches[2]&cpt_onomy_archive=1', 'top' );

   // base rewrite
   add_rewrite_rule( 'movies/directors/([^/]+)/?$', 'index.php?post_type=movies&directors=$matches[1]&cpt_onomy_archive=1', 'top' );
   
   /**
    * The following set of rewrite rules states that if the URL matches this rule,
    * i.e. http://mywebsite.com/movies/steven-spielberg/tom-hanks/, then the page
    * should display all post type 'movies' that are tagged with the first term
    * (which should be from the 'directors' CPT-onomy) and the second term
    * (which should be from the 'actors' CPT-onomy).
    */
   
   // if you want feeds
   add_rewrite_rule( 'movies/([^/]+)/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=movies&directors=$matches[1]&actors=$matches[2]&feed=$matches[3]&cpt_onomy_archive=1', 'top' );
   add_rewrite_rule( 'movies/([^/]+)/([^/]+)/(feed|rdf|rss|rss2|atom)/?$', 'index.php?post_type=movies&directors=$matches[1]&actors=$matches[2]&feed=$matches[3]&cpt_onomy_archive=1', 'top' );

   // if you want pagination
   add_rewrite_rule( 'movies/([^/]+)/([^/]+)/page/?([0-9]{1,})/?$', 'index.php?post_type=movies&directors=$matches[1]&actors=$matches[2]&paged=$matches[3]&cpt_onomy_archive=1', 'top' );

   // base rewrite
   add_rewrite_rule( 'movies/([^/]+)/([^/]+)/?$', 'index.php?post_type=movies&directors=$matches[1]&actors=$matches[2]&cpt_onomy_archive=1', 'top' );

}
?>

How To Add Custom Templates Based On Custom Archive Pages

If you’d like to use a custom template file based on your custom archive page, the ‘template_include’ filter is your friend. Don’t forget that filters must always return a value!

<?php
add_filter( 'template_include', 'my_website_template_include' );
function my_website_template_include( $template ) {
   global $post_type;

   // only include our custom template if we're viewing an archive page
   // with 'movies' posts that are tagged by 'directors'.
   // the is_tax() function will also let you narrow it down
   // by a specific director.
   if ( is_archive() && $post_type == 'movies' && is_tax( 'directors' ) ) {

      // locate_template will first verify that the template exists
      // If it exists, it will return the template URI to be used
      if ( $custom_template = locate_template( 'archive-director-movies.php' ) )
         return $custom_template;

   }

   // A filter must always return a value
   // If your template doesn't exist, it will return the
   // original value passed to the filter.
   return $template;

}
?>