Camen Design

c share + remix

Cleanly Grouping-By

//here follows a lovely way to handle generating HTML whilst grouping by a field. in this instance we have a
//list of items, but we want to wrap each different group in a title and a separate html table. this might seem
//very easy to do, but if you do a normal loop, you only know when the group has changed, after you have the
//next row. you could try looking ahead to predict that, but that would add messy boundary checks.

$rows = array (
	0 => array ('group' => 'hardware', 'name' => 'MacBookPro',   'type' => 'Laptop Computer'),
	1 => array ('group' => 'hardware', 'name' => 'MacMini',      'type' => 'Desktop Computer'),
	2 => array ('group' => 'hardware', 'name' => '5G iPod 60GB', 'type' => 'MP3 Player'),
	3 => array ('group' => 'software', 'name' => 'TextMate',     'type' => 'Text Editor'),
	4 => array ('group' => 'software', 'name' => 'Firefox',      'type' => 'Web Browser')

//we setup a loop that does not move forward (the inner loop does that), this way, when we change the group,
//we can loop back and reprocess the same row for its name and type, which would otherwise get thrown away
//in a standard loop
while ($row =& current ($rows)) {
	//insert the title, remember it as the 'current' group
	$group = $row['group'];
	echo "<h2>$group</h2>\n<table>";
	//this inner loop will build the list of line items, waiting for the group to change
	do {
		//when the group changes, leave the loop
		if ($group != $row['group']) break;
		//output the line item
		echo "	<tr><td>{$row['name']}</td><td>{$row['type']}</td></tr>\n";
	} while ($row =& next ($rows)); //move to the next row, and re-loop
	echo "</table>\n\n";

Often when we are outputting data from our databases, we have the issue of trying to output the HTML in the cleanest method possible. One such nasty mess is often the group-by scenario, whereby one field only changes after so many rows, and not with every single row.

An example of this would be a shop where you are outputting different categories of items, and in your HTML you wish to put a title separating each category.

The problem with doing this elegantly, is that in a normal loop you need to know when the group has changed, ahead of actually dealing with the data in the current iteration of the loop. (because if the group changes, the data in your hands must wait until after you’ve outputted a title)

And then you have the case where the user visits a page where there happens to be only one category, so that your nice code to check for the change of category in the loop has no effect, so you have to repeat the same code again at the end of your loop to catch this condition. (And lord forbid you’d have to use a function to achieve this!)

I looked at this problem and simply didn’t feel happy repeating a piece of code just to handle this look-ahead condition.

Presented here is a solution that cleanly divides rows into their categories, all without having to do anything after the loop, and without failing on single-category lists.

Enjoy :)