pinkp
pinkp

Reputation: 455

SilverStripe 3: How to group a sorted array by grandparent pages

I'm trying to loop through all my ProductPages while grouping them by their grandparent's title (as this is the product category). I would also like to sort the product pages under each group by their ProductReleaseDate descending. Finally if possible, any that do not have a ProductReleaseDate to be listed first before everything.

I have this function in my page controller that grabs all the 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 pages titles in descending order by the ProductReleaseDate they have been given. They now need grouping.

I've been searching hard and can't find the right documentation or examples to get this right. Perhaps I need groupBy? I'm not sure if it needs to be in the controller or the template.

This may help but I need help: http://docs.silverstripe.org/en/developer_guides/model/how_tos/grouping_dataobject_sets/

Upvotes: 3

Views: 763

Answers (1)

3dgoo
3dgoo

Reputation: 15794

In SilverStripe 3.1 we can do this with the GroupedList, the one you linked to in your question.

To set it up we first need something to group the items by. Either a variable or a function that returns a value.

In your case we will set up a get function that returns the grand parent title.

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 a GroupedList.

Page.php

class Page extends SiteTree {

    public function getGroupedProducts() {
        return GroupedList::create(ProductPage::get()->sort('ProductReleaseDate', 'DESC'));
    }

}

Lastly in our template we called our GroupedList function and tell it what to group the items by.

Your template

<% loop $GroupedProducts.GroupedBy(GrandParentTitle) %>
    <h3>$GrandParentTitle</h3>
    <ul>
        <% loop $Children %>
            <li>$Title</li>
        <% end_loop %>
    </ul>
<% end_loop %>

Group by Parent Title

Or if you want to sort by the parent page title first we will 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 GroupedList function that we created before 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 %>

Upvotes: 3

Related Questions