Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Lets use the classic example of a custom post type called "movies", with its own taxonomy called "genre".

By registering the custom post type (with a "movie" slug), the permalinks are already set up for

<domain>/movie/action/ 

...to see all movies in the action genre.

But, archives by date, like

<domain>/2010/09/

...don't know about the custom post type.

The closest date-based archive I'm able to get working is:

<domain>/2010/?post_type=movies

...which lists all the custom post types posted during the current year (2010). For some reason, the month, taxonomy and a term cannot be added to the URL to get the expected result.

What must be done to enable url's like these...

<domain>/2010/09/movie/action/

...to work as expected, thus to list all action movies posted during September 2010?

share|improve this question
add comment

3 Answers 3

Yes, there isn't currently built-in support for CPT archives, but that doesn't mean you can't extend WP to provide it. I just did this myself the other day...

This won't create the date-based archives you're looking for, but it will give you virtual archive behavior for custom post types. Adding the date should just be a matter of tweaking the rewrite rules (actually, date-based permalinks might just work as-is)...

EXAMPLE: you have a custom type of "movies" and single movie post called "gone with the wind". This code will give you a URL structure of website.com/movies/gone-with-the-wind. Also, going to website.com/movies will list just the movies (just like a category archive, though it will not call the archive.php template for output, but will format the output just like the standard index.php loop template).

function register_post_type_archives( $post_type, $base_path = '' ) {
    global $wp_rewrite;
    if ( !$base_path ) {
        $base_path = $post_type;
    }
    $rules = $wp_rewrite->generate_rewrite_rules($base_path);
    $rules[$base_path.'/?$'] = 'index.php?paged=1';
    foreach ( $rules as $regex=>$redirect ) {
        if ( strpos($redirect, 'attachment=') == FALSE ) {
            $redirect .= '&post_type='.$post_type;
            if (  0 < preg_match_all('@\$([0-9])@', $redirect, $matches) ) {
                for ( $i=0 ; $i < count($matches[0]) ; $i++ ) {
                    $redirect = str_replace($matches[0][$i], '$matches['.$matches[1][$i].']', $redirect);
                }
            }
        }
        add_rewrite_rule($regex, $redirect, 'top');
    }
}

call this function right after having generated your custom post type:

register_post_type('movies', $args);
register_post_type_archives('movies');

Then, if you would like to be able to use custom templates to control the output of these quasi-archive listings, you can use this:

add_action('template_redirect', 'post_type_templates');
function post_type_templates() {
    $post_type = get_query_var('post_type');
    if (!empty($post_type)) {
        locate_template(array("{$post_type}.php","index.php"), true);
        die;
    }
}

Now you can create a "movies.php" template in your theme and customize the loop output to your liking..

UPDATE: having the archive functionality for custom types is great, but I realized I needed a way to access them. You can obviously hard-code buttons somewhere that point to the slugs, but I made a function to generate a wp3.0 navbar with all my custom types in it. Right now it spawns a new navbar and makes it the primary, but you could change it to be the secondary, or to just add the items to an existing navbar. Note: the nav links will only work if you're using the rewrite rules from above.

function register_typenav() {
    $mainnav = wp_get_nav_menu_object('Types Nav');
    if (!$mainnav) {
        $menu_id = wp_create_nav_menu( 'Types Nav' );
        // vav item for each post type
        $types = get_post_types( array( 'exclude_from_search' => false ), 'objects' );
        foreach ($types as $type) {
            if (!$type->_builtin) {
                wp_update_nav_menu_item( $menu_id, 0, array(
                    'menu-item-type' => 'custom',
                    'menu-item-title' => $type->labels->name,
                    'menu-item-url' => get_bloginfo('url') . '/' . $type->rewrite['slug'] . '/',
                    'menu-item-status' => 'publish'
                    )
                );
            }
        }
    if ($mainnav && !has_nav_menu( 'primary-menu' ) ) {
        $theme = get_current_theme();
        $mods = get_option("mods_$theme");
        $key = key($mods['nav_menu_locations']);
        $mods['nav_menu_locations'][$key] = $mainnav->term_id;
        update_option("mods_$theme", $mods);
    }
}
add_action('init', 'register_typenav');
share|improve this answer
    
Thanks for this, I'll try it out and accept your answer / propose changes if I can make it work... –  Werner Sep 22 '10 at 14:00
    
This is GREAT! One quick question, how would I add custom taxonomy names as sub items on a menu. –  Brad Sep 26 '10 at 23:23
    
Brad, I guess posting a new question for that is the best way forward, unless somatic edits his post? –  Werner Sep 27 '10 at 11:25
    
that would require a whole new set of code, and would be best as a separate question... which I'd be happy to answer ;-) Werner- have I answered the original question? I would appreciate you choosing my answer as "accepted". –  somatic Oct 10 '10 at 23:58
add comment

Custom Post Types are not designed to provide archive as the common blog post post type does. This might be something that will be changed in the future.

This is the missing link: Custom Post Types (CPT) enhancements that deserve consideration in 3.1.

share|improve this answer
add comment

This plugin provides the exactly what you want. It works well with Wordpress 3.3.1.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.