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
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.