Displaying category archive of custom post types

I am woefully late to the party on Custom Post Types and only started using them quite recently, so apologies if my questions seems idiotic, but I can’t seem to find an answer to my question.

I’ve set up a custom post type called actors with a couple of custom field values, and (crucially), I’m using standard categories to separate these actors into men, women and children listings:

Read More
'taxonomies' => array('category', 'post_tag')

…since I thought that would be a much cleaner and neater way of… well, categorizing the actors. However, I’m completely stumped at how to actually display these categories in any way, shape or form.

I have a custom archive-actors.php file which displays all of the actors, but I want to be able to filter them by category; e.g. only display the men. However if I guess at a standard URL like mysite.com/category/actors/men I just get

Sorry, but there aren’t any posts in the Men category yet.

The same thing happens if I just try mysite.com/category/men – in neither case is it using the archive-actors.php template, either.

Can anyone help clear away my fog of dull-mindedness and point me in the right direction so I can filter out these pesky actors?

Edit:

As @mrwweb alludes to below (and I forgot to mention I had tried), the following can be added to the functions.php file:

function query_post_type($query) {
    $post_types = get_post_types();

    if ( is_category() || is_tag()) {

        $post_type = get_query_var('actors');

        if ( $post_type ) {
            $post_type = $post_type;
        } else {
            $post_type = $post_types;
        }

        $query->set('post_type', $post_type);

        return $query;
    }
}

add_filter('pre_get_posts', 'query_post_type');

…as referenced here which does work, insofar as it will display my categorised custom post types on the regular archive.php page, but doesn’t utilise my archive-actors.php, which is key.

Related posts

Leave a Reply

4 comments

  1. You can force use of your template for categories with the category_template filter:

    function wpa57439_category_template( $templates = '' ){
        if( !is_array( $templates ) && !empty( $templates ) ) {
            $templates = locate_template( array( 'archive-actors.php', $templates ), false );
        } 
        elseif( empty( $templates ) ) {
            $templates = locate_template( 'archive-actors.php', false );
        }
        else {
            $new_template = locate_template( array( 'archive-actors.php' ) );
            if( !empty( $new_template ) ) array_unshift( $templates, $new_template );
        }
        return $templates;
    }
    add_filter( 'category_template', 'wpa57439_category_template' );
    

    adapted from Filter Hierarchy in codex.

  2. That’s the expected behavior of category archives. As found here on the Support forums the following snippet should resolve your issue (just change “article” to your post type):

    add_filter('pre_get_posts', 'query_post_type');
    function query_post_type($query) {
      if(is_category() || is_tag()) {
        $post_type = get_query_var('post_type');
        if($post_type)
            $post_type = $post_type;
        else
            $post_type = array('post','articles','nav_menu_item');
        $query->set('post_type',$post_type);
        return $query;
        }
    }
    

    UPDATE: Gah. I grabbed the wrong snippet. I meant to use this one.

  3. Alternatively, what you can do is just add a new wp_rewrite rule to create a new url structure for displaying only posts in a given cpt and category. Something like the .gist I posted here:

    [edit: can’t embed .gists so here’s the code and linky ]

    /**
    * This could be extrapolated and used for tags or any other taxonomy really.
    */
    
    add_action('init', 'category_cpt_rewrites');
    
    function category_cpt_rewrites() {
        $custom_post_types = array('video', 'audio', 'photo', 'file'); //some example post types
        foreach ( $custom_post_types as $post_type ) {
            $rule = '^' . $post_type . '/category/(.+?)/?$';
            $rewrite = 'index.php?post_type=' . $post_type . '&category_name=$matches[1]';
            add_rewrite_rule($rule,$rewrite,'top');
        }
    }
    
    //make sure you flush rules
    //this will take the following url structure (video cpt as an example, and politics as a category example) -> video/category/politics and return posts belonging to the politics category that are in the "video" custom post type.
    
    //note that if you want this to be truly effective you'll want to make a custom "the_category()" or similar template function to return the correct url structure for a category list belonging to a custom post type post.