WordPress Wednesday: Setting Up Month Archives to Only Display Custom Taxonomy

Geek Factor: 5

This week’s WordPress Wednesday is a bit convoluted, but is the product of a problem I ran across on a recent project.

The blog I was building required that the posts be divided and displayed in two separate groups. This was accomplished by using a different custom taxonomy for each group of posts; that way, each could use a regular set of ‘categories’ from these custom taxonomies, but it would be easy to separate the two.

This was easy to set up for the most part, except for the date-based archives: there is not easy way to divide the archives and wp_get_archive() lists by custom taxonomy (or any taxonomy for that matter!). I did manage to find some code for excluding single categories from wp_get_archives() in the WordPress Support forum, but that’s it!

The solution below built strongly on the category exclusion code linked above, but includes tweaks to display only posts from one custom taxonomy.

First, in your functions.php, add the following:

[php] add_filter( 'getarchives_where', 'customarchives_where' ); add_filter( 'getarchives_join', 'customarchives_join' ); function customarchives_join( $x ) { global $wpdb; return $x . " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)"; } function customarchives_where( $x ) { global $wpdb; // get the IDs for all the terms in the custom taxonomy $categories = get_terms( 'custom-taxonomny-name', 'orderby=id' ); $includeIds; $i = 0; // build a string of those IDs foreach($categories as $category) { if($i != 0) $includeIds .= ','; $includeIds .= $category->term_id; $i++; } return $x . " AND $wpdb->term_taxonomy.taxonomy = 'custom-taxonomny-name' AND $wpdb->term_taxonomy.term_id IN ($includeIds)"; } [/php]

If the filter is applied in the functions.php, it will be applied to all instances of the wp_get_archives() tag. However, if you just want to apply it to some instances in your theme, omit line 1 and 2 in the above code, and add (and remove) the filters around the wp_get_archives() tag when used in the theme:

[php] [/php]

The archives pages will still display the complete archives, whether or not they belong to a specific taxonomy. To counter this, we can first adjust the archive pages so that they only display archives from a specific taxonomy. The below code creates a query for posts only in our custom taxonomy, then merges that with the archive’s default query:

[php] query, array( 'tax_query' => array( array( 'taxonomy' => $tax, 'field' => 'id', 'terms' => get_terms($tax, array( 'fields' => 'ids' )) ) ) )); query_posts( $args ); ?> [/php]

Of course, we may not want all archive pages to display only posts from the custom taxonomy. And we also want to be able to link to the taxonomy-specific archives from our filtered wp_get_archive(). To get around this, we will add a query string to the URLs in our filtered wp_get_archive() that specifies our custom taxonomy; this will be used to adjust the query on our archive page.

First, adding the query string to wp_get_archives():

[php] [/php]

Now all the URLs will have the query string ?tax=taxonomy-name.

Next, we will wrap this tweaked wp_get_archives() in our filter from the functions.php:

[php mark="3,4,19,20"]

Now this instance of the wp_get_archives() will only display months that have posts in our custom taxonomy, and include the query string in each of the links.

Lastly, on our archives page, we will need to ‘catch’ our query string by adding this to the top of the template used for archives – this will get the value of our query string and save it in a variable:

[php] $customTaxonomy = $_GET['tax']; [/php]

Next, we will add and if() statement around our modified archive query that checks for the existence of our query string (lines 2 and 17). The post query will only be altered to show posts from our custom taxonomy if the page has been passed our query string:

[php mark="2,17"] query, array( 'tax_query' => array( array( 'taxonomy' => $tax, 'field' => 'id', 'terms' => get_terms($tax, array( 'fields' => 'ids' )) ) ) )); query_posts( $args ); } ?> [/php]

This way, when the archive page is displayed without the query string in the URL, it will display normally; when it is displayed with the query string (therefore, accessed from our filtered wp_get_archives() links) it will only display posts that are part of our custom taxonomy.

This code isn’t the most elegant, but it solved the issue at hand, and got the site templates working the way I wanted. If anyone has suggestions about how to tighten this up, I’d be happy to hear them!

Leave a Comment

Note: Fields marked with a * are required; email addresses are not published.

Legal FAQ Collections