Thank you! Your feedback has been delivered
Thank you! Your feedback has been sent

Wordpress CPT date archive

Hi folks,

I'm building a site that has a few custom post types (CPT) set up and specifically I have one called 'Blog'. Below I have included my functions inclusion of this Blog CPT. The issue I am having is that although I can get the archives page for the CPT working using the archive-blog.php template, I can't work out how to get date archive working, or output a list of months for each post (using wp_list_archives. I have managed to get wp_list archives using the following code:

function my_custom_post_type_archive_where($where,$args){  
    $post_type  = isset($args['post_type'])  ? $args['post_type']  : 'post';  
    $where = "WHERE post_type = '$post_type' AND post_status = 'publish'";
    return $where;  
}
add_filter('getarchives_where', 'my_custom_post_type_archive_where', 10, 2);

<?php wp_get_archives( array( 'type' => 'monthly', 'post_type' => 'blog', 'limit' => 10 ) ); ?>

// Blog CPT
add_action( 'init', 'register_cpt_blog' );
function register_cpt_blog() {
    $labels = array( 
        'name' => _x( 'Blog', 'blog' ),
        'singular_name' => _x( 'Blog', 'blog' ),
        'add_new' => _x( 'Add New', 'blog' ),
        'add_new_item' => _x( 'Add new blog', 'blog' ),
        'edit_item' => _x( 'Edit blog', 'blog' ),
        'new_item' => _x( 'New blog', 'blog' ),
        'view_item' => _x( 'View blog', 'blog' ),
        'search_items' => _x( 'Search blog', 'blog' ),
        'not_found' => _x( 'No blog found', 'blog' ),
        'not_found_in_trash' => _x( 'No blog found in Trash', 'blog' ),
        'parent_item_colon' => _x( 'Parent Blog:', 'blog' ),
        'menu_name' => _x( 'Blog', 'blog' ),
    );
    $args = array( 
        'labels' => $labels,
        'hierarchical' => true,
        'description' => 'A section of blogs',
        'supports' => array( 'title', 'editor' ),
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'menu_position' => 21,
        'show_in_nav_menus' => true,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => array('slug' => 'blog'),
        'capability_type' => 'post'
    );
    register_post_type( 'blog', $args );
}

I have a development site set up so you can see how it currently works: http://dev.rdck.co/ssk/blog/

Thanks, R

User Gravatar

user-1043706

Posted Jun 23 2014 2:51 UTC

$25



10 Replies


Add this to your functions.php, and then use register_post_type_with_dates() instead of register_post_type()

<?php


/**
 * Same that register_post_type() with archives per date
 *
 * http://codex.wordpress.org/Function_Reference/register_post_type
 */
function register_post_type_with_dates( $post_type, $args = array() )
{
    $inst = new Custom_Post_Type_With_Dates($post_type, $args);
    return $inst->args;
}


/**
 * Internal usage
 */
class Custom_Post_Type_With_Dates
{
    public $post_type;
    public $args;

    public function __construct( $post_type, $args = array() ) {
        $this->post_type = $post_type;
        $this->args = $args;
        $this->args = $this->_register_post_type();

        add_action('rewrite_rules_array', array(&$this, 'rewrite_rules_array'), 100);
        add_action('wp_loaded', array(&$this, 'wp_loaded'));
        add_filter('date_template', array(&$this, 'date_template'));
    }

    protected function _register_post_type() {
        return register_post_type($this->post_type, $this->args);
    }

    public function rewrite_rules_array( $rules ) {
        if ( ! empty($this->args->has_archive) && is_string($this->args->has_archive)) {
            $slug = $this->args->has_archive;
        } else {
            $slug = $this->post_type;
        }
        $new_rules = $this->_get_new_rules();

        return ($new_rules + $rules);
    }

    public function wp_loaded() {
        $test_key = current(array_keys($this->_get_new_rules()));
        $rules = (array) get_option('rewrite_rules');
        if ( ! array_key_exists($test_key, $rules)) {
            global $wp_rewrite;
            $wp_rewrite->flush_rules();
        }
    }

    public function date_template( $template ) {
        $templates = array();
        if (get_query_var('post_type') == $this->post_type) {
            $templates[] = "date-{$this->post_type}.php"; 
            $templates[] = "archive-{$this->post_type}.php"; 
        }
        $templates[] = $template;

        return locate_template( $templates );
    }

    protected function _get_new_rules() {
        $post_type = $this->post_type;
        if (isset($this->args->has_archive) && is_string($this->args->has_archive)) {
            $slug = $this->args->has_archive;
        } else {
            $slug = $post_type;
        }

        return array(
            "{$slug}/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&feed=$matches[4]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&feed=$matches[4]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/page/?([0-9]{1,})/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&paged=$matches[4]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/feed/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&feed=$matches[3]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&feed=$matches[3]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/page/?([0-9]{1,})/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]&paged=$matches[3]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/([0-9]{1,2})/?$" => 'index.php?year=$matches[1]&monthnum=$matches[2]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/feed/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&feed=$matches[2]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/(feed|rdf|rss|rss2|atom)/?$" => 'index.php?year=$matches[1]&feed=$matches[2]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/page/?([0-9]{1,})/?$" => 'index.php?year=$matches[1]&paged=$matches[2]' . '&post_type=' .  $post_type,
            "{$slug}/([0-9]{4})/?$" => 'index.php?year=$matches[1]' . '&post_type=' .  $post_type,
        );
    }
}

source

User Gravatar

omgmog

Posted Jun 23 2014 7:40 UTC

Thanks for this help @omgmog.

This seems to work well if I type http://dev.rdck.co/ssk/blog/2011/08/ but the default usage of wp_get_archives churns out http://dev.rdck.co/ssk/2011/08/ without the blog (slug/CPT) part. Any ideas how I can achieve this.

Also, for dates that don't have any posts http://dev.rdck.co/ssk/blog/2013/08/, for example, it shows some random things. Any way I can make it 404?

Thanks, R

User Gravatar

user-1043706

Posted Jun 23 2014 12:21 UTC

You can use the following to add your custom post types to the result of wp_get_archives. Add these to your functions.php, duplicating for each custom post type and changing blog to whatever your custom post type is:

add_action( 'pre_get_posts', 'blog_add_to_posts' ); 

function blog_add_to_posts( $query ) { 
    $post_type = $query->get( 'post_type' ); 
    if ( empty( $post_type ) ||  'post' == $post_type ) {
        $query->set( 'post_type', array( 'post', 'blog' ) ); 
    }
} 

add_filter( 'getarchives_where', 'blog_getarchives_where' ); 

function blog_getarchives_where( $where ) { 
    return str_replace( "WHERE post_type = 'post'", "WHERE post_type IN ('post', 'blog')", $where ); 
} 
User Gravatar

omgmog

Posted Jun 23 2014 13:01 UTC

Thanks @omgmog – how would I then call this? For example:

<?php wp_get_archives( array( 'type' => 'monthly', 'post_type' => 'blog', 'limit' => 10 ) ); ?>
User Gravatar

user-1043706

Posted Jun 23 2014 13:07 UTC

Sorry forgot that step.

Yes you should be able to call it like that, but you can omit the post_type:

<?php 
add_filter( 'getarchives_where', 'blog_getarchives_where' ); 
wp_get_archives( array( 'type' => 'monthly', 'limit' => 10 ) ); 
remove_filter( 'getarchives_where', 'blog_getarchives_where' ); 
?>
User Gravatar

omgmog

Posted Jun 23 2014 13:17 UTC

Okay, so I added the first solution to my functions.php file, then added the wp_get_archives to my header where I want the list to appear, but then I get this error:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'blog_getarchives_where' not found or invalid function name in /Users/richgcook/Sites/Freelance/ssk/wp-includes/plugin.php on line 192
June 2014
User Gravatar

user-1043706

Posted Jun 24 2014 0:21 UTC

Any update on this so you can get your reward?

User Gravatar

user-1043706

Posted Jun 25 2014 11:34 UTC

Sorry, this should be back open now @omgmog... so any help to complete this would be great.

User Gravatar

user-1043706

Posted Jun 25 2014 13:47 UTC

Just a thought for you in case you get stuck... this plugin just released by a fellow working on a core WordPress patch for date archives for CPTs might do just what you need.

https://github.com/jacklenox/archives-for-custom-post-types

One thing about the above plugin, pagination for the archives doesn't work yet but he will add the simple fix for that in the next update.

Another option is this plugin which is supposed to allow support date archives for CPTs as well, though I've not had luck with it:

https://wordpress.org/plugins/custom-post-type-permalinks/

User Gravatar

creativelogic

Posted Jun 25 2014 20:27 UTC

Solution

This didn't solve your task? Get your own custom solution.

Hi @creativelogic... wow that plugin was a great find (https://github.com/jacklenox/archives-for-custom-post-types) so thank you for this. No problem re pagination for now... and look forward to the next update for the fix! Hopefully not too long! It's nice to know they are looking at building this into the core... about time!

Many thanks! R

User Gravatar

user-1043706

Posted Jun 26 2014 0:45 UTC

Add a reply

By posting a reply on CodersClan you agree to our Terms & Conditions