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.

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!

share|improve this question
    
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... –  t f Nov 6 '13 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 Nov 6 '13 at 0:43
add comment

1 Answer

up vote 0 down vote accepted

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.

share|improve this answer
    
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 Nov 6 '13 at 1:15
    
yes, correct. and you're welcome! –  Milo Nov 6 '13 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 Nov 6 '13 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 Nov 6 '13 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 Nov 6 '13 at 18:43
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.