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.

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!

  • You almost did everything there is to do. After your Upcoming Events query just add another WP_Query with according arguments. And don't forget to call wp_reset_postdata after you're finished, in order you want to work with the original query in some way...
    – tfrommen
    Commented Nov 6, 2013 at 0:14
  • Thanks for the feedback! It sounds like if I did this both upcoming & past events would be displayed at once. I'd like the default to upcoming with an option to show past instead (but not both at the same time). Would this require the creation of a separate template file (and if so, where would it go)?
    – Eric
    Commented Nov 6, 2013 at 0:43

1 Answer 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_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.

  • Wow, thanks for the very thorough response! I assume I would then just manually add a link to events/past (or something along those lines) in the archive-event.php template to change between queries?
    – Eric
    Commented Nov 6, 2013 at 1:15
  • yes, correct. and you're welcome!
    – Milo
    Commented Nov 6, 2013 at 1:28
  • Okay, I added those functions as well as <a href="<?php bloginfo('url'); ?>/events/past">Past Events</a> to the archive-event.php page (and removed the original query there) – but the query doesn't seem to be switching over. I flushed the rewrite rules as well. Is this the correct usage here?
    – Eric
    Commented Nov 6, 2013 at 1:48
  • add var_dump( $wp_query ); to your template and inspect the query vars to make sure they're getting set correctly. I'd also suggest disabling your cache plugin to be sure there isn't a conflict. and add a training slash to your past events link, you're getting an extra http request / redirect each time WordPress forwards to the version with the trailing slash.
    – Milo
    Commented Nov 6, 2013 at 2:52
  • Thanks again – I got everything working now! I just noticed I was still calling if ($the_query -> have_posts() ) instead of just if ( have_posts() ). Once I reverted to the default query everything fell into place.
    – Eric
    Commented Nov 6, 2013 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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