0

For a project of mine I have set up three custom fields (Year, month, day) attached to posts in order to determine the original date of a post’s content (not the post publish date, which is used for ordering in a different template). For an archive/category view I have successfully arranged to have them ordered by year (custom field: date_year), then month (date_month), then day(date_day) via the following query arguments:

'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_query' => array(
    array(
        'key' => 'date_year',
        'value' => '',
        'compare' => 'LIKE'
    ),
    array(
        'key' => 'date_month',
        'value' => '',
        'compare' => 'LIKE'
    ),
    array(
        'key' => 'date_day',
        'value' => '',
        'compare' => 'LIKE'
    )
)

However, the project would require to separate each year’s posts into a separate div, each with a unique ID, e.g.

<div id="year-2015">
<!-- All posts from 2015, ordered by month and then day -->
</div>
<div id="year-2014">
...
</div>

Is there an easy way to do so? How would I have to query in order to achieve this? Or would you in general (even though the project requires three separate fields) suggest one field and then explode it to retrieve the year for separating into divs?

Update 1

One single date field (format Y-m-d: e.g. "2015-02-18") would be even better, as it turns out. A basic query would be

$args = array(
    'cat' => 14,
    'post_type' => 'post',
    'posts_per_page' => -1,
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
    'meta_key' => 'p2f_date'
);

in order to have normal order via date field as intended, but of course there is no grouping by year so far.

  • You can use sql query with $wpdb – Fatih SARI Feb 15 '15 at 9:19
  • Thanks, that’s an option. Could you elaborate on that more, possibly with a code example on how to actually solve this particular matter ;)? – physalis Feb 15 '15 at 12:05
0

A single field would be enough but if you manage your way with 3 that's good as well.

I would do a loop through the results and end up with a structure like the following:

$years = array(
    '2015' => array(
        <WP_Post object>,
        <WP_Post object>,
        etc...
    ),
    '2016' => array(
        etc...
    )
);

Then you could go through this arrays again to build your html.

A lot of different technics can be used in that case. Just use your favorite I guess. I just think doing one database call is better than 3.

Not sure if I answer your question but I hope it helps.

EDIT:

Since you are ordering by date, you don't need to re-order your result so it should be as easy as :

/* Your custom query */
$args = array(
    'cat' => 14,
    'post_type' => 'post',
    'posts_per_page' => -1,
    'orderby' => 'meta_value_num',
    'order' => 'DESC',
    'meta_key' => 'p2f_date'
);

$archive = new WP_Query( $args );

$current_year = null;


/* if our query has posts */
if( $archive->have_posts() ){

    /* loop through them */
    while( $archive->have_posts() ){
        $archive->the_post();

        $p2f_date = get_post_meta( get_the_id(), 'p2f_date' );

        /* Here I skip if the meta is not defined but you might want to handle that differently */
        if(empty($p2f_date)){
            continue;   
        }

        /* Get the year - Depending how you handle the post meta you might not need the index [0] */
        $year = date('Y', strtotime( $p2f_date[0] ));

        if( $current_year === null ){
            /* First item */
?>
           <ul class='year year--<?php echo $year; ?>'>
<?php 
        }else if( $current_year !== $year ){
            /* New section */
        ?>
            </ul>
            <ul class='year year--<?php echo $year; ?>'>
           <?php   
        }

        ?>
        <li>
            <a href='<?php the_permalink(); ?>'><?php the_title(); ?></a>
        </li>
        <?php

        $current_year = $year;
    }

    ?>
    </ul>
    <?php

}

/* Reset your page data in case you need it after the custom query */
wp_reset_postdata();

Hope that makes sense and answers your question. Here I used a custom WP_Query but you could just change the main query if this is relevant in your case.

  • How would I do that exactly (just a PHP beginner here)? From the looks of your example it seems I would have to manually loop in every year - which would get messy and problematic ;). – physalis Feb 15 '15 at 12:06
  • Do you have a hint on how to achieve this, @mathieuhays? I am currently switching to a single date field with Y-m-d data inside, which would seem a bit easier so far. – physalis Feb 18 '15 at 14:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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