0

I have posts under a custom post type which I like to display in a page grouped by Year and Month. In the page template that I create, I managed to separate them by month, but still without grouping at separate levels (they're all same-level, there's just the month name as a break between the groups), like so:

<div class="month"></div>
<div>post title</div>
<div>post title</div>
<div>post title</div>
<div>post title</div>
<div class="month"></div>
<div>post title</div>
<div>post title</div>
<div>post title</div>
<div>post title</div>
<div class="month"></div>
<div>post title</div>
<div>post title</div>
<div>post title</div>
<div>post title</div>

I did that with:

<?php
global $more; $more = false; # some wordpress wtf logic
$posts = get_posts(array(
    'post_type' => 'press',
    'nopaging' => true,
    'orderby' => 'date',
    'order' => 'DSC',
    'posts_per_page'   => 999999,
    ));

$month = null;

foreach($posts as $post): 

    setup_postdata($post); //enables the_title() etc. without specifying a post ID
    $postMonth =  date('FY',strtotime($post->post_date));

    if($month!=$postMonth){
        echo '<div class="month">'.date('F Y',strtotime($post->post_date)).'</div>';        
        $month =$postMonth;
    } ?>

    <div><a href="<?php the_field('url');?>">"<?php the_title();?>"</a></div>

<?php endforeach;?>

What I want to have is something like this:

<div class="year">
    <span>2019</span>
    <div class="month">
        <span>August</span>
            <div>post title</div>
            <div>post title</div>
    </div>
</div>
<div class="year">
    <span>2019</span>
    <div class="month">
        <span>July</span>
            <div>post title</div>
            <div>post title</div>
    </div>
</div>
<div class="year">
    <span>2018</span>
    <div class="month">
        <span>January</span>
            <div>post title</div>
            <div>post title</div>
    </div>
</div>

I tried pretty every solution I could find on StackExchange to no avail. Any ideas?

1 Answer 1

2

You can do it like so:

global $post;

$posts = get_posts( array(
    'post_type' => 'press',
    'nopaging'  => true,
    'orderby'   => 'date',
    'order'     => 'DESC', // it's DESC; not DSC
    // There's no use setting posts_per_page when nopaging is enabled.
    // Because posts_per_page will be ignored when nopaging is enabled.
) );

$_year_mon = '';   // previous year-month value
$_has_grp = false; // TRUE if a group was opened
foreach ( $posts as $post ) {
    setup_postdata( $post );

    $time = strtotime( $post->post_date );
    $year = date( 'Y', $time );
    $mon = date( 'F', $time );
    $year_mon = "$year-$mon";

    // Open a new group.
    if ( $year_mon !== $_year_mon ) {
        // Close previous group, if any.
        if ( $_has_grp ) {
            echo '</div><!-- .month -->';
            echo '</div><!-- .year -->';
        }
        $_has_grp = true;

        echo '<div class="year">';
        echo "<span>$year</span>";

        echo '<div class="month">';
        echo "<span>$mon</span>";
    }

    // Display post title.
    if ( $title = get_the_title() ) {
        echo "<div>$title</div>";
    } else {
        echo "<div>#{$post->ID}</div>";
    }

    $_year_mon = $year_mon;
}

// Close the last group, if any.
if ( $_has_grp ) {
    echo '</div><!-- .month -->';
    echo '</div><!-- .year -->';
}

wp_reset_postdata();
1
  • 1
    Like a charm. Tnx buddy
    – MAR
    Aug 12, 2019 at 8:36

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.