0

Basically a post is an event therefor will be displayed once or twice, depending on meta key. Every post has at least two meta keys $start_time_1 and $end_time_1. Let's say i have two posts, title: "Radio Show" and "TV Show".

Radio Show - start @ 2016-07-01 12:00
TV Show - start @ 2016-07-01 15:00

My code below, works fine. But what if i add another start time like $start_time_2and $end_time_2 and all post sorted by start time. Just like this:

Radio Show - start @ 2016-07-01 12:30
TV Show - start @ 2016-07-01 15:30
TV Show - start @ 2016-07-02 21:00 
Radio Show - start @ 2016-02-01 23:00

This the query i'using but i cant make to show the post twice.

$start_time_1 = '2016-07-01 12:30';
$end_time_1 = '2016-07-01 14:30';

$args = array(
'post_type'        => 'post',
'posts_per_page'   => -1,
'post_status'      => 'publish',
'meta_query' => array(
array(
'key' => $end_time_1, // if the time() is greater than end time dont display post
'value' => date('Y-m-d H:i'),
'compare' => '>='
)),
'meta_key' => $start_time_1, // for sorting posts
'orderby'  => array( 
'meta_value' => 'ASC', 
'post_date'      => 'ASC',
),  
'order' => 'ASC',
);
1
  • Hmmm interesting question. This isn't how WP_Query works; posts are only meant to be returned once. I don't know if you could this, without a custom database query. codex.wordpress.org/Class_Reference/wpdb is where you'd need to start.
    – Tim Malone
    Commented Jul 1, 2016 at 5:37

2 Answers 2

1

As Tim Malone said, WP_Query isn't going to return multiple copies of the same post in its result set. I think you have a design problem and I would suggest you use parent/child posts rather than post meta to accomplish what you want.

The following is one approach to doing this. First, register both post types:

// The parent event type
// There will be one of these for Radio Show and TV Show
register_post_type( 'event', $args );

// A non-public event type for each "occurrence" of an event
// There will be two of these for each Radio Show and TV Show
register_post_type( 'event_occurrence', array(
    // add all of your usual $args and then set public to false
    'public' => false,
) );

Then, when saving your event post, don't save the start/end times as post meta on that post object. Instead use those dates to create event_occurrence posts for each occurrence, with the start and end times saved there.

$occurrence_id = wp_insert_post( array(
    // add all of your occurrence details and then set the parent
    // to the `event` post that's being saved
    'post_parent' => <event_post_id>,

    // Set the post date to the start time for efficient ordering
    'post_date' => $start_time,
) );

// Save the end time as post meta
// Save it as a Unix timestamp so that we can compare it in the query
update_post_meta( $occurrence_id, 'end_time', strtotime( $end_time ) );

Now you should have the following posts in the database:

Radio Show
    Radio Show Instance 1
    Radio Show Instance 2
TV Show
    TV Show Instance 1
    TV Show Instance 2

You can then query the occurrences like this:

$args = array(

    // Only fetch occurrences
    'post_type' => 'event_occurrence',

    // Retrieve only future occurrences
    'date_query' => array(
        array(
            'after' => 'now',
        )
    ),

    // use a reasonably high posts_per_page instead of -1
    // otherwise you could accidentally cripple a site
    // with an expensive query
    'posts_per_page' => 500,

    'post_status' => 'publish',

    'meta_query' => array(
        array(
            'key' => 'end_time',
            'value' => time(),
            'compare' => '>='
        ),
    ),

    // They'll be ordered by start date.
    // ASC starts with earliest first
    'order' => 'ASC',
);

Our loop will now contain four posts:

Radio Show Instance 1
Radio Show Instance 2
TV Show Instance 1
TV Show Instance 2

So while you're looping through the occurrences, you can access the parent post of each occurrence to get the overall event data. You can do this with a simple function:

$parent_event_id = wp_get_post_parent_id( get_the_ID() );

However, this will result in a lot of extra queries to the database which will effect performance. Instead, I'd recommend you run a separate query for the primary event posts, and then pull them from those results, so you're only making one additional query to the database:

$args = array(
    'post_type' => 'event',
    'date_query' => array(
        array(
            'after' => 'now',
        )
    ),
    'posts_per_page' => 500,
    'post_status' => 'publish',
    'meta_query' => array(
        array(
            'key' => 'end_time',
            'value' => time(),
            'compare' => '>='
        ),
    ),
    'order' => 'ASC',
);
$events = new WP_Query( $args );

So your $occurrences loop would look like this:

$occurrences = new WP_Query( $occurrences_args );
while( $occurrences->have_posts() ) {
    $occurrences->the_post();

    // Get the parent event data
    $parent_event_id = wp_get_post_parent_id( get_the_ID() );
    $parent_event = null;
    foreach ( $events->posts as $post ) {
        if ( $post->ID == $parent_event_id ) {
            $parent_event = $post;
            break;
        }
    }

    // Now you can use the loop to access the
    // occurrence data and use $parent_event to
    // access the overall event data
}
0

What about using this?

$args = array(
    'post_type' => 'post',
    'posts_per_page' => -1,
    'post_status' => 'publish',
    'meta_query' => array(
        'relation' => 'OR',
        array(
            'key' => $end_time_1,
            'value' => date('Y-m-d H:i'),
            'compare' => '>='
        ),
        array(
            'key' => $end_time_2,
            'value' => date('Y-m-d H:i'),
            'compare' => '>='
        )
    ),
    'meta_key' => $start_time_1,
    'orderby'  => array( 
        'meta_value' => 'ASC', 
        'post_date' => 'ASC',
    ),
    'order' => 'ASC',
);

I think you can use nested relationships to do a more comprehensive query.

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.