skip to Main Content

I have this query which returns a list of post titles for the current event.

<ul class="event-category-list no-margin no-list-style">
<?php 
    $current_category = get_queried_object();
    $args = array(
        'post_type'         => 'event',
        'posts_per_page'    => -1,
        'tax_query'         => array(
            array(
                'taxonomy' => 'event-type',
                'field'    => 'term_id',
                'terms'    => $current_category->term_id,
            ),
        ),
    );
    $query = new WP_Query($args);
    while ($query->have_posts()) : $query->the_post();

    ?>

        <li>
            <?php echo the_title(); ?>
        </li>

    <?php endwhile;
    wp_reset_postdata();
?>
</ul>

It works fine.

Also, each post has an ACF date repeater subfield called event_date (format is Ymd) which can have one or more dates.

What also needs to happen

I need my query to not return posts where all instances of the event_date are in the past.

Explaining by example

Let’s say the event is a Foo Fighters concert, and it’s over three dates: 20230726, 20230727 and 20230728 (the ACF date repeater subfield event_date has those three dates).

enter image description here

If all of those dates are in the past, the post title should not be returned.

2

Answers


  1. Instead of working with an ACF repeater fields directly in a meta_query (which would need a more complex SQL queries, such as using a JOIN operation with a subquery), you can consider:

    • fetching all events without filtering them by the event_date subfield in the query itself,
    • and then filters the results using a loop in PHP.
    <ul class="event-category-list no-margin no-list-style">
    <?php
        $current_category = get_queried_object();
        $today = date('Ymd'); // Get today's date in the same format as the ACF subfield
    
        $args = array(
            'post_type'         => 'event',
            'posts_per_page'    => -1,
            'tax_query'         => array(
                array(
                    'taxonomy' => 'event-type',
                    'field'    => 'term_id',
                    'terms'    => $current_category->term_id,
                ),
            ),
        );
    
        $query = new WP_Query($args);
        while ($query->have_posts()) : $query->the_post();
            // Loop through the event_date repeater subfield
            $event_dates = get_field('event_date');
            $is_future_event = false;
    
            foreach ($event_dates as $event_date) {
                if ($event_date >= $today) {
                    $is_future_event = true;
                    break;
                }
            }
    
            // Only display the title if the event has at least one date today or in the future
            if ($is_future_event) {
        ?>
    
            <li>
                <?php echo the_title(); ?>
            </li>
    
        <?php 
            } 
        endwhile;
        wp_reset_postdata();
    ?>
    </ul>
    

    In the functions.php file of your theme (wp-content/themes/my-theme/functions.php), you can add:

    function wpza_replace_event_date_field( $where ) {
        $where = str_replace( "meta_key = 'event_date_$", "meta_key LIKE 'event_date_%", $where );
        return $where;
    }
    add_filter( 'posts_where', 'wpza_replace_event_date_field' );
    

    The wpza_replace_event_date_field() function is hooked to the posts_where filter using the add_filter() function in the functions.php file

    When a new WP_Query is created and executed, WordPress internally builds the SQL query. During this process, it triggers the posts_where filter, and any functions hooked to this filter will be called.
    In this case, the wpza_replace_event_date_field() function will be called, and it will modify the SQL WHERE clause to search for all meta keys that match the pattern event_date_{index}_event_date.
    By doing so, it ensures that the SQL query includes all rows with keys that represent the event_date subfield of the ACF repeater.

    The loop (while ($query->have_posts()) : $query->the_post(); ... endwhile;) checks if the event has at least one date today or in the future, and if so, it displays the title of the event.
    The indirect effect of the wpza_replace_event_date_field() function is that the WP_Query will return posts with event_date subfields that match the criteria defined in the meta_query.

    Login or Signup to reply.
  2. You can use meta_query param for compare dates:

    <ul class="event-category-list no-margin no-list-style">
    <?php
        $current_category = get_queried_object();
        $args = array(
            'post_type'         => 'event',
            'posts_per_page'    => -1,
            'tax_query'         => array(
                array(
                    'taxonomy' => 'event-type',
                    'field'    => 'term_id',
                    'terms'    => $current_category->term_id,
                ),
            ),
            'meta_query'    => array(
                'relation'      => 'AND',
                array(
                    'key'       => 'event_date',
                    'value'     => date('Y-m-d'),
                    'compare'   => '>='
                )
            )
        );
        $query = new WP_Query($args);
        while ($query->have_posts()) : $query->the_post();
    
        ?>
    
            <li>
                <?php echo the_title(); ?>
            </li>
    
        <?php endwhile;
        wp_reset_postdata();
    ?>
    </ul>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search