This document contains information for an outdated version (2.4) and may not be maintained any more.

If some of your projects still use this version, consider upgrading as soon as possible.

Grouping Data Object Sets

The DataObjectSet class has a number of methods useful for grouping objects by fields. Together with sorting this can be used to break up long lists of data into more manageable sub-sections.

The DataObjectSet->groupBy()&version=2.4&module=framework) method takes a field name as the single argument, and breaks the set up into a number of arrays, where each array contains only objects with the same value of that field. The DataObjectSet->GroupedBy()&version=2.4&module=framework) method builds on this and returns the same data in a template-friendly format.

Grouping Sets By First Letter

This example deals with breaking up a DataObjectSet into sub-headings by the first letter.

Let's say you have a set of Module objects, each representing a SilverStripe module, and you want to output a list of these in alphabetical order, with each letter as a heading; something like the following list:

*    B
    * Blog
*    C
    * CMS Workflow
    * Custom Translations
*    D
    * Database Plumber
    * ...

The first step is to set up the basic data model, along with a method that returns the first letter of the title. This will be used both for grouping and for the title in the template.

class Module extends DataObject {
    public static $db = array(
        'Title' => 'Varchar(255)'
    );
    // ...
    /**
     * Returns the first letter of the module title, used for grouping.
     *
     * @return string
     */
    public function getTitleFirstLetter() {
        return $this->Title[0];
    }
}

The next step is to create a method or variable that will contain/return all the Module objects, sorted by title. For this example this will be a method on the Page class.

class Page extends SiteTree {
    // ...
    /**
     * Returns all modules, sorted by their title.
     *
     * @return DataObjectSet
     */
    public function getModules() {
        return DataObject::get('Module', null, '"Title"');
    }
}

The final step is to render this into a template. The DataObjectSet->GroupedBy()&version=2.4&module=framework) method breaks up the set into a number of sets, grouped by the field that is passed as the parameter. In this case, the getTitleFirstLetter method defined earlier is used to break them up.

// Modules list grouped by TitleFirstLetter
<h2>Modules</h2>
<% control Modules.GroupedBy(TitleFirstLetter) %>
    <h3>$TitleFirstLetter</h3>
    <ul>
        <% control Children %>
            <li>$Title</li>
        <% end_control %>
    </ul>
<% end_control %>

Grouping Sets By Month

Grouping a set by month is a very similar process. The only difference would be to sort the records by month name, and then create a method on the DataObject that returns the month name, and pass that to the DataObjectSet->GroupedBy()&version=2.4&module=framework) call.

Again, the first step is to create a method on the class in question that will be displayed in a list. For this example, a DataObject called NewsItem will be used. This will have a method which returns the month it was posted in:

class NewsItem extends DataObject {
    public static $db = array(
        'Title' => 'Varchar(255)',
        'Date'  => 'Date'
    );
    // ...
    /**
     * Returns the month name this news item was posted in.
     *
     * @return string
     */
    public function getMonthPosted() {
        return date('F', strtotime($this->Date));
    }
}

The next step is to create a method that will return all the News records that exist, sorted by month name from January to December. This can be accomplshed by sorting by the Date field:

class Page extends SiteTree {
    /**
     * Returns all news items, sorted by the month they were posted
     *
     * @return DataObjectSet
     */
    public function getNewsItems() {
        return DataObject::get('NewsItem', null, '"Date"');
    }
}

The final step is the render this into the template using the DataObjectSet->GroupedBy()&version=2.4&module=framework) method.

// Modules list grouped by the Month Posted
<h2>Modules</h2>
<% control NewsItems.GroupedBy(MonthPosted) %>
    <h3>$MonthPosted</h3>
    <ul>
        <% control Children %>
            <li>$Title ($Date.Nice)</li>
        <% end_control %>
    </ul>
<% end_control %>

Comments

Comment policy: Please use comments for tips and corrections about the described functionality.
Comments are moderated, we reserve the right to remove comments that are inappropriate or are no longer relevant. Use the Silverstripe Forum to ask questions.

blog comments powered by Disqus