Support

Account

Home Forums ACF PRO Sort post by acf date first and after by title

Solved

Sort post by acf date first and after by title

  • Hello everybody,
    I have an issue on a website.
    I need to display movies (my custom post: ‘films’) and some have a release date (ACF field : ‘date_de_sortie’) and others do not have one.
    I would like to display in first movies with release date (from the the closer to the further ) and only after, those which don’t have a release date (ordered by title).

    For now it displays in first movies without a release date in and after those with a release date, order is ok.
    Here is my function :

    
    add_action( 'pre_get_posts', 'films_query' );
    function films_query( $query ) {
    if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
    $cat_hide = get_field('categorie_des_films_a_masquer', 'options');
    $taxquery = array(
    array(
    'taxonomy' => 'categorie_films',
    'field' => 'term_id',
    'terms'    => $cat_hide,
    'operator' => 'NOT IN',
    )
    );
    $query->set( 'posts_per_page', '-1' );
    $query->set( 'post_status', 'publish' );
    
    $query->set( 'meta_key', 'date_de_sortie' );
    $query->set( 'orderby', 'meta_value title' );
    $query->set( 'order', 'ASC' );
    
    $query->set( 'tax_query', $taxquery );
    }
    }
    

    Do I need to use $query->set( ‘meta_query’, $meta_query ); with $meta_query args ?
    Any help appreciated.
    All the best.
    Pierre

  • If you want to sort by an acf field and something else then you must use a meta query with clauses.

    See the code example labeled
    ‘orderby’ with multiple ‘meta_key’s

    https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters

    the difference here that you would use post_title for the second part of the order by instead of 2 meta clauses.

  • Hello @hube2,
    Thanks for taking on your time to answer.
    I’ll have a look at the codex.
    I’ll keep you in touch.
    Thanks.
    Pierre

  • Here is with meta_query args but it didn’t work, I have the same results.
    There is something I don’t understands.

    
    add_action( 'pre_get_posts', 'films_query' );
    function films_query( $query ) {
      if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
        $cat_hide = get_field('categorie_des_films_a_masquer', 'options');
        $taxquery = array(
          array(
            'taxonomy' => 'categorie_films',
            'field' => 'term_id',
            'terms'    => $cat_hide,
            'operator' => 'NOT IN',
          )
        );
    
        $query->set( 'posts_per_page', '-1' );
        $query->set( 'post_status', 'publish' );
    
        $query->set( 'tax_query', $taxquery );
        $query->set( 'meta_query', array(
          'relation' => 'AND',
          'date' => array(
            'key' => 'date_de_sortie',
            'compare' => 'EXISTS',
          )
        )
      );
      $query->set( 'orderby', array(
        'date' => 'ASC',
        'title'   => 'ASC',
      )
    );
    }
    }
    
  • Here is the new code with meta_query but same results.
    There is something I don’t understand…

    
    add_action( 'pre_get_posts', 'films_query' );
    function films_query( $query ) {
      if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
        $cat_hide = get_field('categorie_des_films_a_masquer', 'options');
        $taxquery = array(
          array(
            'taxonomy' => 'categorie_films',
            'field' => 'term_id',
            'terms'    => $cat_hide,
            'operator' => 'NOT IN',
          )
        );
        $query->set( 'posts_per_page', '-1' );
        $query->set( 'post_status', 'publish' );
        $query->set( 'tax_query', $taxquery );
        $query->set( 'meta_query', array(
          'relation' => 'AND',
          'date' => array(
            'key' => 'date_de_sortie',
            'compare' => 'EXISTS',
          )
        )
      );
      $query->set( 'orderby', array(
        'date' => 'ASC',
        'title'   => 'ASC',
      )
    );
    }
    }
    
  • Here is the new code with meta_query, but same result.
    Any idea on what I’m missing ?

    
    add_action( 'pre_get_posts', 'films_query' );
    function films_query( $query ) {
      if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
        $cat_hide = get_field('categorie_des_films_a_masquer', 'options');
        $taxquery = array(
          array(
            'taxonomy' => 'categorie_films',
            'field' => 'term_id',
            'terms'    => $cat_hide,
            'operator' => 'NOT IN',
          )
        );
        $query->set( 'posts_per_page', '-1' );
        $query->set( 'post_status', 'publish' );
        $query->set( 'tax_query', $taxquery );
        $query->set( 'meta_query', array(
          'relation' => 'AND',
          'date' => array(
            'key' => 'date_de_sortie',
            'compare' => 'EXISTS',
            )
          )
        );
        $query->set( 'orderby', array(
          'date' => 'ASC',
          'title'   => 'ASC',
          )
        );
      }
    }
    
  • Hello everybody,
    sorry to be pushy, any idea how to solve it ?
    Thank you in advance.
    Best.
    Pierre

  • the issue is that “date” is a reserved word so it cannot be used as a clause name. WP will ignore your clause name and use the post date.

    Try something like “date_clause”

  • Hello @hube2
    Ok, oh yes I understand.
    I tried with “date_clause” and unfortunately it’s still the same…
    Here is the updated code :

    
    add_action( 'pre_get_posts', 'films_query' );
    function films_query( $query ) {
      if ( !is_admin() && $query->is_main_query() && is_post_type_archive( 'films' ) ) {
        $cat_hide = get_field('categorie_des_films_a_masquer', 'options');
        $taxquery = array(
          array(
            'taxonomy' => 'categorie_films',
            'field' => 'term_id',
            'terms'    => $cat_hide,
            'operator' => 'NOT IN',
          )
        );
        $query->set( 'posts_per_page', '-1' );
        $query->set( 'post_status', 'publish' );
        $query->set( 'tax_query', $taxquery );
        $query->set( 'meta_query', array(
          'relation' => 'AND',
          'date_clause' => array(
            'key' => 'date_de_sortie',
            'compare' => 'EXISTS',
            )
          )
        );
        $query->set( 'orderby', array(
          'date_clause' => 'ASC',
          'title'   => 'ASC',
          )
        );
      }
    }
    
  • I don’t see any reason that is should not be working.

    Are you sure that the if statement is correct and that your code is running?

    Have you tried removing the tax query to see if that is interfering?

    Does the field ‘date_de_sortie’ actually exist in the DB on the posts you are trying to sort?

  • Me neither… I don’t understand.
    Yes my code is running.
    I tried running it with :

    
    //$query->set( 'tax_query', $taxquery );
    

    It doesn’t interfer.
    The field ‘date_de_sortie’ is my ACF date picker field.
    If I set ‘date_clause’ => ‘DESC’, it effectively sorts posts in the opposite direction which is logical, but always posts without any ‘date_de_sortie’ are in first.
    Hope I’m clear in my explanations ;-).
    Best.
    Pierre

  • By your explanation I am assuming that the date field exists for all posts but is empty on some posts have an empty value == ''

    Even if a value is empty, it “EXISTS”

    if that is the case then you should be looking for a meta values that != ''

  • @hube2 yes it’s exact, the date field exist but is empty on some posts.
    I have updated to :

    
        $query->set( 'meta_query', array(
          'relation' => 'AND',
          'date_clause' => array(
            'key' => 'date_de_sortie',
            'value' => '',
            'compare' => '!=',
            )
          )
        );
    

    Now it displays only posts with date field not empty.
    Posts whith empty date field are not displayed.

  • I tried again today, I didn’t reach to do what I’m looking for.
    Maybe I need a new approach, any thoughts ?
    Best

  • It sounded to me like you had it working in the previous reply. I guess I don’t understand what you are trying to do.

  • Hello @hube2,
    Thanks again for taking time for me and my issue…
    I’m sorry, I think I’m not explaining myself well.
    I would like to display first the posts (CPT : films) that have a date (acf date picker field : date_de_sortie) and then those that do not.
    Currently they display first those without a date.
    I made a photomontage to explain what I’m looking for (I framed date on it to see where date is).
    Here is the photomontage
    All the best.
    Pierre

  • It is not possible to short the posts in the way that you want to sort them. In MySQL empty strings are less than non-empty strings. When sorting in ASC order they will always come first. If you use number as the data type the value would be 0 (zero) again lower than any post with a date.

    There are really 2 choices

    1) ensure that every post has a value

    2) do 2 queries, first get all posts with a value and then get all posts with empty values.

  • Ok, I think the second choice seems to the better solution.
    What do you think ?

  • There is a 3rd choice I just thought of.

    You could do one query, loop over the posts once to show the ones that have a date and then loop over them a second time to show posts without a date. Given that you are showing all posts this might be the way I would go.

    
    // posts with date value
    While (have_posts()) {
      the_post();
      if (get_field('date_field') == '') {
        // skip it
        continue;
      }
      // show this post
    }
    rewind_posts();
    // posts without date value
    while (have_posts()) {
      the_post();
      if (get_field('date_field') != '') {
        // end of posts without date, exit loop
        break;
      }
      // show this post
    }
    
    
  • @hube2,
    Many thanks !!
    This third solution seems to be very cool.
    I need to do it as a “pre_get_posts” function with my $taxquery so as to hide some custom taxonomies.
    I never did a loop inside a function inside my functions.php, the loop is inside my archives-films.php.
    I have to test this, I will do it tomorrow and keep you in touch.
    Thanks for all.
    Best.
    Pierre

  • Hello @hube2,
    I followed your advice and I did a query directly inside my archive template with your 3rd choice.
    And it works like a charm.
    You’re the best.
    Thank you so much !!
    All the best.
    Pierre

Viewing 21 posts - 1 through 21 (of 21 total)

You must be logged in to reply to this topic.