I have an expiry date ACF field 'post_end_date' which has been applied to multiple post types, including 'post'.

I'm trying to filter out any posts, across the entire site, where today's date is greater than the value 'post_end_date'; in other words the post has expired. I've checked that 'post_end_date' value returns a number in the same format as date('Ymd'). e.g.

echo date('Ymd'); // returns 20161128 for today
echo get_field('post_end_date'); // returns 20161127 for yesterday

I figured the best way would be to just do a numerical comparison between today's date and 'post_end_date' value.

This is my code:

  function expiry_filter($query) {

    if( !is_admin() && $query->is_main_query() ) :

      $today = $expire = date('Ymd');

      if ( get_field('post_end_date') ) :
        $expire = get_field('post_end_date');
      endif;

      $query->set( 'meta_query', array(
        array(
         'key'     => $expire,
         'value'   => $today,
         'compare' => '<',
         'type'    => 'NUMERIC'
        )
      ));

    endif;
  }
  add_action( 'pre_get_posts', 'expiry_filter' );

At this point, I was just trying to get it to work for the 'post' post type. I have checked that I haven't used the wrong 'compare' operator. I've tried with and without the $query->is_main_query() conditional.

The result I'm getting with the code above is ALL posts are being filtered out.

Can someone suggest what I might be doing wrong here?

Thanks in advance.

  • You should check your values. 'key' => $expire will result in 'key' => 20161128 or something. Shouldn't it be 'key' => 'post_end_date'? – Fabian Marz Nov 29 '16 at 17:54
  • Good point @FabianMarz ! So, when making the adjustment I now get only the posts that should be filtered out showing with < as the comparator, which makes sense. So it is matching the meta_query now, but how do I invert it to remove those that match, rather than remove everything that doesn't match? Swapping compare operator to >= filters out everything – Rhecil Codes Nov 29 '16 at 18:49
  • >= should to the trick. Have you checked your values? get_field will refer to the current post which can lead to unexpected results as you hook in the main query. So maybe there is no post from today? – Fabian Marz Nov 29 '16 at 18:56
  • OK. I follow you @FabianMarz. Last question: How do I adjust to include posts where post_end_date is not set? Or do I do an if ( get_field('post_end_date') ): around the $query->set? If you submit as an answer, I will mark your reply as the answer. – Rhecil Codes Nov 29 '16 at 19:07
up vote 0 down vote accepted

As mentioned in the comments you an issue in your meta query, as you set the key to 20161126 or similar. Instead key should be filled with your meta key post_end_date. Meta query also support multiple arrays to combine your query to also include posts where the meta key is not set. The example would be something like the following:

function expiry_filter($query) {
  if( !is_admin() && $query->is_main_query() ) {
    $expire = get_field('post_end_date') ? : date('Ymd');
    $query->set( 'meta_query', [
      'relation' => 'OR',
      [
       'key'     => 'post_end_date',
       'value'   => $expire,
       'compare' => '>=',
       'type'    => 'NUMERIC',
      ],
      [
       'key'     => 'post_end_date',
       'compare' => 'NOT EXISTS',
      ],
    ]);
  }
}
add_action( 'pre_get_posts', 'expiry_filter' );

Have you tried using meta_key, meta_value and meta_compare?

function expiry_filter( $query ) {

    if ( ! is_admin() && $query->is_main_query() ) :

        $query->set( 'meta_key', 'post_end_date' );
        $query->set( 'meta_value', date('Ymd') );
        $query->set( 'meta_compare', '>' );

    endif;
}

add_action( 'pre_get_posts', 'expiry_filter' );

Or maybe trying to use the DATE type when using meta_query?

function expiry_filter( $query ) {

  if ( ! is_admin() && $query->is_main_query() ) :

      $query->set( 'meta_query', array(
          array(
              'key'     => 'post_end_date',
              'value'   => date( 'Ymd' ),
              'compare' => '>=',
              'type'    => 'DATE'
          )
      ) );

  endif;
}
add_action( 'pre_get_posts', 'expiry_filter' );

Or just using the cleaned up version of your function

function expiry_filter( $query ) {

  if ( ! is_admin() && $query->is_main_query() ) :

      $query->set( 'meta_query', array(
          array(
              'key'     => 'post_end_date',
              'value'   => date( 'Ymd' ),
              'compare' => '>',
              'type'    => 'NUMERIC'
          )
      ) );

  endif;
}
add_action( 'pre_get_posts', 'expiry_filter' );

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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