SilverStripe 3: How to Group a Sorted Array by Grandparents Pages
I'm trying to skip all mine ProductPage
by grouping them by their grandparents' title (since this is a product category). I would also like to sort the product pages under each group in descending order ProductReleaseDate
. Finally, if possible, any that don't ProductReleaseDate
have to be listed first before everything.
I have this function in my page controller that grabs all product pages:
function ProductPages() {
$productPages = ProductPage::get();
return $productPages ? $productPages : false;
}
Then in my template:
<% loop $ProductPages.Sort(ProductReleaseDate, DESC) %>
$Title
<% end_loop %>
This displays all my product titles in descending order with the ProductReleaseDate they got. Now they need a grouping.
I have searched a lot and cannot find the correct documentation or examples to get it right. Maybe I need a group? I'm not sure if it should be in the controller or template.
It might help, but I need help: http://docs.silverstripe.org/en/developer_guides/model/how_tos/grouping_dataobject_sets/
In SilverStripe 3.1 we can do this with the help GroupedList
you linked to in your question.
To customize it, we first need something to group the elements. Either a variable or a function that returns a value.
In your case, we'll create a get function that returns the title of the big parent.
ProductPage.php
class ProductPage extends SiteTree {
public function getGrandParentTitle() {
$parent = $this->Parent();
if ($parent->Exists()) {
$grandParent = $parent->Parent();
if ($grandParent->Exists()){
return $grandParent->Title;
}
}
return '';
}
}
Then we need to add a function that will return GroupedList
.
page.php
class Page extends SiteTree {
public function getGroupedProducts() {
return GroupedList::create(ProductPage::get()->sort('ProductReleaseDate', 'DESC'));
}
}
Finally, in our template, we called our function GroupedList
and told it to group the elements.
Your template
<% loop $GroupedProducts.GroupedBy(GrandParentTitle) %>
<h3>$GrandParentTitle</h3>
<ul>
<% loop $Children %>
<li>$Title</li>
<% end_loop %>
</ul>
<% end_loop %>
Parent title group
Or, if you want to sort the title of the parent page first, we'll set up a get function that returns the parent title.
ProductPage.php
class ProductPage extends SiteTree {
public function getParentTitle() {
$parent = $this->Parent();
if ($parent->Exists()) {
return $parent->Title;
}
return '';
}
}
Then in our template, we called our function GroupedList
that we created earlier, but this time set GroupedBy
to ParentTitle
.
Your template
<% loop $GroupedProducts.GroupedBy(ParentTitle) %>
<h3>$ParentTitle</h3>
<ul>
<% loop $Children %>
<li>$Title</li>
<% end_loop %>
</ul>
<% end_loop %>