Support

Account

Home Forums ACF PRO Get Next Post Reply To: Get Next Post

  • The first thing that I would do is store these event dates into something that can more easily be searched in a simple meta_query, like I said above, searches based on repeater sub fields are a PITA that I avoid.

    
    <?php 
      
      // step 1: store event_date in a queryable form
      // this is done as a class, the reason is storage of
      // each value that has been saved
      class store_repeater_sub_field_in_standard_wp_meta {
        
        // this array will store values that have already been saved
        // more about this later
        private $fields = array();
        
        public function __construct() {
          // this is where we add the filters
          // use the field keys here because it is a sub field
          // this class will work on multiple fields by adding the
          // filter multiple times, once for each field key
          // all values stored into new fields will be identical to values stored by ACF
          add_filter('acf/update_value/key=field_123456', array($this, 'convert_sub_field'), 10, 3);
        } // end public function __construct
        
        public function convert_sub_field($value, $post_id, $field) {
          // get the field key
          $field_key = $field['key'];
          // get the field name
          $field_name = $field['name'];
          // create a new field name based on the current field name
          $queryable_name = 'queryable_'.$field_name;
          
          // first step is to see if we've already saved any values for this field
          if (!isset($this->fields[$field_key])) {
            // there is not value set in the property for this key
            // no values have been updated yet
            // clear any existing values from the queryable field
            delete_post_meta($post_id, $queryable_name);
            // add a nested array to the property to hold values
            // for this field, this will also ensure that we don't
            // delete them again since the field has a value in the property
            $this->fields[$field_key] = array();
          }
          // see if we've already saved this value for this field
          // there really is not point saving the same value twice
          if (!in_array($value, $this->fields[$field_key])) {
            // not there, add it the values
            $this->fields[$field_key][] = $value;
            // and add it to the database
            add_post_meta($post_id, $queryable_name, false);
            // the last argument above says that this is not a unique meta key
            // and will hold multiple values
          }
          // return the original value for ACF to process as normal
          return $value;
        } // end public function convert_sub_field
        
      } // end class store_repeater_sub_field_in_standard_wp_meta
      
      // instantiate the object
      new store_repeater_sub_field_in_standard_wp_meta();
      
    ?>
    

    I know that what is above can seem extreme, but this was fairly easy to do (if you remove all the comments there is actually very little code there) and now we can construct extremely simple queries instead of complex LIKE queries and adding filters to add LIKE to the meta_key part of the query because we are querying a sub field.

    
    // current date
    $current_date = date{'Ymd');
    // get the next event from now
    $args = array(
      'post_type' => 'event',
      'post_status' => 'publish',
      'posts_per_page' => 1, // or the number of next dates you want
      'meta_key' => 'queryable_event_date',
      'order_by' => 'meta_value',
      'order' => 'ASC',
      'meta_query' => array(
        'key' => 'queryable_event_date',
        'value' => $date,
        'compare' => '>='
      ),
    );
    $next_event_query = new WP_Query($args);
    

    during the loop for the “next_event” query, collect a list of posts show so that they are not returned in the next query.

    
    // other code before loop
    $events_shown = array();
    if ($next_event_query->have_posts()) {
      while ($next_event_query->have_posts()) {
        $next_event_query->the_post();
        $events_shown[] = $post->ID;
        // other code to display the next event post
      }
      wp_reset_postdata()
    }
    

    Then use the values collected in $events_shown to not get those events again

    
    $args = array(
      'post_type' => 'event',
      'post_status' => 'publish',
      'posts_per_page' => 1, // or the number of next dates you want
      'meta_key' => 'queryable_event_date',
      'order_by' => 'meta_value',
      'order' => 'ASC',
      'meta_query' => array(
        'key' => 'queryable_event_date',
        'value' => $date,
        'compare' => '>='
      ),
      'posts__not_in' => $events_shown,
    );
    $event_query = new WP_Query($args);
    

    I’m sure that you could also construct a single query and loop to do this, but I tend toward a less complex coding style that lets me more easily understand what I was thinking when I need to look at it again in a year because something needs to be changed.

    Hope this helps