0

Problem: I want to list posts of a category, displaying those with custom-field 'start-date' after today (in the future) with order ASC. When this is done, I want to display all those with start-date before today (in the past) with order DESC.

The second list is no problem.

But the first list only displays the single most recent post when I use order => 'ASC'. If I use order => 'DESC', all the posts display correctly.

Where do I fail in this code?

    $args = array(
                        'cat' => $cat_id,
                        'meta_key' => 'dato-start',
                        'orderby' => 'meta_value_num',
                        'order' => 'ASC',
                        'paged' => $paged
                    );
                    
    $arrangementer = new WP_Query($args);
    if ( $arrangementer->have_posts() ) :
       while ( $arrangementer->have_posts() ) : $arrangementer->the_post();

            $today = date('Ymd');
            $unnagjort = FALSE;
            $startDato = get_post_meta(get_the_ID(), 'dato-start', TRUE);
            $sluttDato = get_post_meta(get_the_ID(), 'dato-slutt', TRUE);;


            if ( get_field('dato-start') && ($today > $startDato) ) $unnagjort = TRUE;          
                
            if (!$unnagjort)    {
                get_template_part( 'template-parts/content', get_post_format() );
            }

            endwhile;

Then I run rewind_posts() and the same query, but order DESC, and filter out those with $unnagjort == TRUE.

The first query returns only the most recent requested post, the second returns all the requested posts.

2
  • what format are the dates in the dato-start post meta values saved in? Are they a MySQL standard format? Do you have examples?
    – Tom J Nowell
    Commented Jan 16, 2023 at 15:19
  • Echoing $startDato displays like this: 20230131
    – hal
    Commented Jan 16, 2023 at 15:30

1 Answer 1

1

There are 3 problems here

It's Using a Non-Standard Date Format

The dates are being stored like this:

20230131

Which is ok for us as we can interpret that as a date with no spaces, but it needs to stored like this:

2023 01 31

Specifically, it needs to be timestamp like this:

YYYY-MM-DD HH:MM:SS

or this:

YYYY-MM-DD

You can choose a different separator, and there is some flexibility over how the date is formatted, e.g. YY/MM/DD also works, as does Y-M-D, as long as the year comes before the month, and the month comes before the day.

You will need to convert all your existing data to use a consistent timestamp format.

It Does Not Use Date Based Ordering

Once the above change has been made, the date oriented options become available, e.g. you could do this:

$args = [
    'meta_query' => [
        [
            'key'     => 'release_date',
            'value'   =>  array( '2019-01-01', '2019-12-31' ),
            'type'    =>  'date',
            'compare' =>  'between'   
        ]
    ]
];
 
$query = new WP_Query($args);

This also means you could do:

$args = [
    'meta_key'  => 'release_date',
    'meta_type' => 'DATE',
    'orderby'   => 'meta_value',
];
 
$query = new WP_Query($args);

The Loop Check

In the main loop there is this code:

            if ( get_field('dato-start') && ($today > $startDato) ) $unnagjort = TRUE;          
                
            if (!$unnagjort)    {
                get_template_part( 'template-parts/content', get_post_format() );
            }

You've assumed because only 1 post is shown that the WP_Query parameters are wrong, but actually, it's more likely because of this check. If it fetches 10 posts but $unnagjort is only false once, it will show 1 post, how would you tell this apart from it fetching a single post? Even if there are more posts, it will only return them 10 or so at a time!

Instead, add a meta_query to WP_Query and make that do the work of filtering them out instead of doing it in PHP. Ask for all posts that have a start date earlier than today, for example:

$args = [
    'meta_query' => [
        [
            'key'     => 'release_date',
            'value'   =>  date('Y-M-D');,
            'type'    =>  'date',
            'compare' =>  '<'   
        ]
    ]
];

Then your if check can be eliminated, and it will only return the posts you want

3
  • Thank you very much, you are obviously right. However, I can't give up hoping that I still could use my existing data, as comparing the dates as numbers in my head would return the same results? Of course using your meta_query method, instead of filtering in php. Or am I completely wrong?
    – hal
    Commented Jan 16, 2023 at 21:53
  • Tested: it works the way I suggested. Thanks again!
    – hal
    Commented Jan 16, 2023 at 22:20
  • 😞 you can use a WP_Query to fetch all the posts and switch the meta over, this isn't the only reason to migrate your dates from a number to a date, and fixing it isn't as hard or as big a task as it might seem.
    – Tom J Nowell
    Commented Jan 17, 2023 at 9:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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