Jump to content

Group by Year and Month but prevent month title repitition


jarvis
 Share

Recommended Posts

Hi All,

Hope you're well! I rather hope someone can help.

I've got the following code which queries a database and returns results. I'm then trying to loop the results and group by year, then within a year, group by month. The code works but outputs the following:

2022
April
- Title 4
April
- Title 3
March
- Title 2

2021
December
- Title 1

As you can see, if a month has more than one result, it displays the month name twice. What I'd like is:

2022
April
- Title 4
- Title 3
March
- Title 2

2021
December
- Title 1

Here's my code:
 

<?php
global $wpdb;	
$post_type = 'offers';
$post_status = 'publish';
$expiry_date = 'expiry_date';
$results = $wpdb->get_results( 
	$wpdb->prepare("
	SELECT P.ID, P.post_title as Title, meta_value as 'Expiry Date', DATE_FORMAT(meta_value, '%Y') as Year, DATE_FORMAT(meta_value, '%m') as Month
	FROM {$wpdb->prefix}posts AS P
	LEFT JOIN {$wpdb->prefix}postmeta AS PM on PM.post_id = P.ID
	WHERE P.post_type = %s and P.post_status = %s and ( meta_key = %s )",
	$post_type, $post_status, $expiry_date) 
);

$count_month_map = array();
foreach ($results as $result) :
	if(array_key_exists($result->Year, $count_month_map)) :
		array_push($count_month_map[ $result->Year ], $result);
	else:
		$count_month_map[ $result->Year ] = Array( $result );
	endif;
endforeach;

$last_year = 0;

if( $count_month_map ):

	foreach ($count_month_map as $year => $month) :
	?>
		<h3><?php echo $year; ?></h3>
		<?php 
		rsort($month); 
		foreach ($month as $key) : 
		?>

			<h4><?php echo $monthName = date('F', mktime(0, 0, 0, $key->Month, 10)); ?></h4>
			<?php
			$featured_img_url = get_the_post_thumbnail_url($key->ID, 'thumbnail'); #full
			if ( ! empty( $featured_img_url ) ):
			?>
			<img src="<?php echo esc_url($featured_img_url); ?>" class="img-fluid" />
			<?php endif; ?>
			<p><a href="<?php echo get_permalink($key->ID); ?>" title="<?php echo $key->Title; ?>"><?php echo $key->Title; ?></a></p>

		<?php endforeach;
	endforeach; 
endif; 
?>

I'm not sure if I've approached this correctly, so any help is very much appreciated

Thank you

Link to comment
Share on other sites

when you fetch and index/pivot the data, index it by both the year and the month -

$data = [];
foreach ($results as $result)
{
	$data[$result->Year][$result->Month][] = $result;
}

to produce the output -

foreach($data as $year=>$arr)
{
	// start a new year section here...
	echo "<h3>$year</h3>";
	foreach($arr as $month=>$rows)
	{
		// start a new month section here...
		$monthName = date('F', mktime(0, 0, 0, $month, 10));
		echo "<h4>$monthName</h4>";
		foreach($rows as $row)
		{
			// output the data under each month here...
			echo "<p>$row->Title</p>";
		}
	}
}

 

  • Great Answer 1
Link to comment
Share on other sites

Thank you so much @mac_gyver

I really appreciate that. I'd been playing around with:

$data = array();
foreach($results as $event){
    if(isset($event->Year)){
        #$data[$event->Year][$event->Month]['ID']= $event->ID;
        #$data[$event->Year][$event->Month]['Title'] = $event->Title;
		$data[$event->Year][$event->Month]['Title'] = $event->Title;
		#$data[$event->Month][]['Month'] = $event->Month;
    } else {
        $data[$event->Year] = array($event->Title);
    }
}

So I wasn't a million miles away - although your code made it sooo much easier!

Thank you once again!

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.