Help splitting a custom post type archive into “past” and “upcoming”

I’m working on a wordpress site that keeps track of a series of event posts (custom post type), and I’d like to split up my archive-event.php page into two sections – “upcoming events” and “past events,” based on today’s date.

Using meta_query, I’ve been able to successfully show only events which have not yet happened, based on today’s date. Changing my query to show past events instead of future ones should not be difficult.

Read More

What I don’t understand is how to enable both of these queries at the same time. Is there a way to create a second archive-post-type.php page for my custom post type? Alternatively, is there a way to create a new page template (ex. past-events.php) and somehow connect add it into the site’s template hierarchy?

By way of context, the page I’m trying to modify is here: http://artsrestore.la/events/

And you can see the archive-event.php code here: https://gist.github.com/egardner/7324310

Many thanks,
Eric

Also – I’m pretty new at wordpress and PHP generally, so explanations of code are greatly appreciated!

Related posts

1 comment

  1. The first thing we can do to make this more efficient, is to get rid of the query in your post type archive template. That page is already loading your events in the main query, and you’re then running a new query in the template, so this is a waste of a query.

    What we’ll do instead is use the pre_get_posts action to add the meta query before the main query is run. We can then use the normal while( have_posts() ) loop in the template, and not the custom query loop. There’s an extra bit in here to handle past events that won’t make sense until the next step, so keep reading:

    function event_post_order( $query ){
        // if this is not an admin screen,
        // and is the event post type archive
        // and is the main query
        if( ! is_admin()
            && $query->is_post_type_archive( 'event' )
            && $query->is_main_query() ){
    
            // if this is a past events view
            // set compare to before today,
            // otherwise set to today or later
            $compare = isset( $query->query_vars['is_past'] ) ? '<' : '>=';
    
            // add the meta query and use the $compare var
            $today = date( 'Y-m-d' );
            $meta_query = array( array( 
                'key' => 'sort_date',
                'value' => $today,
                'compare' => $compare,
                'type' => 'DATE'
            ) );
            $query->set( 'meta_query', $meta_query );
        }
    }
    add_action( 'pre_get_posts', 'event_post_order' );
    

    Now to get the past events working, we’ll add a couple of rewrite rules to handle events/past, plus pagination. Your archive-event.php template will be used for both upcoming and past, so no need for new templates.

    This is also where we add the is_past rewrite tag, so we can check in the previous step if it’s a past events view:

    function event_archive_rewrites(){
        add_rewrite_tag( '%is_past%','([^&]+)' );
        add_rewrite_rule(
            'events/past/page/([0-9]+)/?$',
            'index.php?post_type=event&paged=$matches[1]&is_past=true',
            'top'
        );
        add_rewrite_rule(
            'events/past/?$',
            'index.php?post_type=event&is_past=true',
            'top'
        );
    }
    add_action( 'init', 'event_archive_rewrites' );
    

    So that’s it. Visit your Settings > Permalinks admin page after adding this code to your theme’s functions.php file to flush rewrite rules, or you could put it in a plugin.

Comments are closed.