BitPoet Posted March 21, 2018 Share Posted March 21, 2018 (edited) Not sure where the best place for this is, but I felt like sharing a little snippet for site/ready.php I wrote that creates a PageArray::groupBy method: <?php /** * * Adds a groupBy method to all PageArray instances. * * Returns a nested array, with the values of the page properties whose names * were passed as arguments as the keys. * * Usage: * ====== * * $grouped = $mypagearray->groupBy(field1 [, field2 ...] [, mutator_function]); * or * $grouped = $mypagearray->groupBy(mutator_function); * * Example: * ======== * * $mypagearray = $pages->find("template=blog-post, sort=year, sort=month"); * $grouped = $mypagearray->groupBy("year", "month"); * * foreach($grouped as $year => $monthgroup) { * echo "<div class='year'><h2>$year</h2>" . PHP_EOL; * echo "\t<ul class='month'>" . PHP_EOL; * * foreach($monthgroup as $month => $mypages) { * echo "\t\t<li><h3>$month</h3>" . PHP_EOL; * * echo "\t\t\t<ul class='post'>" . PHP_EOL; * * foreach($mypages as $post) { * echo "\t\t\t\t<li><a href='{$post->url}'>{$post->title}</a></li>" . PHP_EOL; * } * * echo "\t\t\t</ul>\n" . PHP_EOL; * echo "\t\t</li>\n" . PHP_EOL; * } * * echo "\t</li>" . PHP_EOL; * echo "</ul>" . PHP_EOL; * } * * Example Output: * =============== * * <div class='year'><h2>2016</h2> * <ul class='month'> * <li><h3>1</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-10/grouptest-10-10/'>Group Test 10 10</a></li> * <li><a href='/grouptest/grouptest-6/grouptest-6-10/'>Group Test 6 10</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-12/'>Group Test 10 12</a></li> * <li><a href='/grouptest/grouptest-1/grouptest-1-12/'>Group Test 1 12</a></li> * <li><a href='/grouptest/grouptest-5/grouptest-5-3/'>Group Test 5 3</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-4/'>Group Test 10 4</a></li> * <li><a href='/grouptest/grouptest-3/'>Group Test 3</a></li> * <li><a href='/grouptest/grouptest-6/grouptest-6-4/'>Group Test 6 4</a></li> * <li><a href='/grouptest/grouptest-10/grouptest-10-7/'>Group Test 10 7</a></li> * </ul> * * </li> * * <li><h3>2</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-5/grouptest-5-10/'>Group Test 5 10</a></li> * <li><a href='/grouptest/grouptest-3/grouptest-3-7/'>Group Test 3 7</a></li> * <li><a href='/grouptest/grouptest-9/grouptest-9-5/'>Group Test 9 5</a></li> * <li><a href='/grouptest/grouptest-7/grouptest-7-12/'>Group Test 7 12</a></li> * <li><a href='/grouptest/grouptest-3/grouptest-3-11/'>Group Test 3 11</a></li> * <li><a href='/grouptest/grouptest-9/grouptest-9-11/'>Group Test 9 11</a></li> * </ul> * * </li> * * <li><h3>3</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-7/grouptest-7-10/'>Group Test 7 10</a></li> * <li><a href='/grouptest/grouptest-12/grouptest-12-12/'>Group Test 12 12</a></li> * <li><a href='/grouptest/grouptest-11/grouptest-11-5/'>Group Test 11 5</a></li> * </ul> * * </li> * * <li><h3>4</h3> * <ul class='post'> * <li><a href='/grouptest/grouptest-8/grouptest-8-3/'>Group Test 8 3</a></li> * <li><a href='/grouptest/grouptest-12/grouptest-12-6/'>Group Test 12 6</a></li> * </ul> * * </li> * * </li> * </ul> * * IMPORTANT! * ========== * * Your PageArray needs to be sorted by the fields you group by, or your return array will be an * unorderly mess (the grouping is still correct, but the order of keys is arbitrary). * * Mutator Function: * ================= * * Instead of just reading properties from the page, you can also pass a mutator function * to groupBy. It gets passed the page object as its first arguments and any optional property * names after that. * * This might come in handy if you want to group by year and month but only have a single * DateTime field. You can then use a grouping function like this: * * $blogposts = $pages->find("template=blog-post, sort=created"); * $grouped = $blogposts->groupBy(function($pg) { * return array(strftime('%Y', $pg->created), strftime('%m', $pg->created)); * }); * */ wire()->addHook("PageArray::groupBy", function(HookEvent $event) { $out = array(); $args = $event->arguments(); if(count($args) == 0) throw new InvalidArgumentException("Missing arguments for function PageArray::groupBy, at least 1 required!"); $last = count($args) - 1; $fnc = is_string($args[$last]) ? FALSE : array_pop($args); foreach($event->object as $pg) { if($fnc) { $props = call_user_func_array($fnc, array_merge(array($pg), $args)); } else { $props = array_map(function($propname) use($pg) { return $pg->{$propname}; }, $args); } $cur = &$out; foreach($props as $prop) { if(!isset($cur[$prop])) $cur[$prop] = array(); $cur = &$cur[$prop]; } $cur[] = $pg; } $event->return = $out; }); Edited February 25 by BitPoet Fixed more typos 14 1 Link to comment Share on other sites More sharing options...
rick Posted March 21, 2018 Share Posted March 21, 2018 How did you know I was needing this functionality just today. Great stuff! Thanks! 1 Link to comment Share on other sites More sharing options...
Robin S Posted March 22, 2018 Share Posted March 22, 2018 Thanks @BitPoet! I think there might be some typos in the mutator example - maybe you meant: $blogposts = $pages->find("template=blog-post, sort=created"); $grouped = $blogposts->groupBy(function($pg) { return array(strftime('%Y', $pg->created), strftime('%m', $pg->created)); }); 6 Link to comment Share on other sites More sharing options...
BitPoet Posted March 22, 2018 Author Share Posted March 22, 2018 54 minutes ago, Robin S said: I think there might be some typos in the mutator example Definitely. Thank for pointing that out, I have ammended my post. 4 Link to comment Share on other sites More sharing options...
gmclelland Posted January 3 Share Posted January 3 Thanks for sharing BitPoet! I did notice a couple of typos as well: * echo "<div class='year'><h2>$year</h3>" . PHP_EOL; and <div class='year'><h2>2016</h3> Notice the h2 and h3 don't match up? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now