Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Data Model Questions /

Best method to alphabetize Data?


Reply


5 Posts   2177 Views

Avatar
Mohammed

Community Member, 25 Posts

2 February 2010 at 7:48pm

Hi,

I've been trying to find a way to list many different items in an organized way.

Specifically, to accomplish the following:

A Page that will display in list format-

Name of School Department (sorted alphabetically by the department name)
Faculty belonging to that School Department (sorted alphabetically by Faculty's Lastname)

Desired output (sample):

Anatomy: Fred Cooks, Bart Deport, Lenny Yelisky
Math: Jonny Alfords, Matt Macking, Adam Zipper
Zoology: Pikurt Adams, Escce Cocks, Jonny Zypho

In the above sample, the Departments and the Department's Faculty are listed in alphabetical order.

I tried to follow tutorial:5-dataobject-relationship-management ([url]http://doc.silverstripe.org/doku.php?id=tutorial:5-dataobject-relationship-management[/url]); however, I was not able to get the Departments to sort automatically since it was using the SiteTree. Plus, Faculty was sorted based off the creation date, not Lastname. I tried to install the dataobjectmanager, however, that didn't seem to help...

I then tried to use the method described here-->[url]http://doc.silverstripe.org/doku.php?id=recipes:alphabetical_dataobjectset[/url] however I wasn't able to get that to work either.

I know there is an easy way to accomplish this; I just don't know what it is. Any help would be greatly appreciated!

(using SilverStripe CMS - 2.3.5)

Avatar
banal

Community Member, 901 Posts

2 February 2010 at 9:14pm

Hi

You can sort relation objects by passing arguments to the relation getter. For example, if you got the following $has_many relation:

public static $has_many = array(
   'Faculties' => 'Faculty'
);

Then you can create a sorted output with a method like this:

public function getSortedFaculties(){
   return $this->Faculties(null, 'Lastname, Firstname');
}

The first argument can be a where statement (left as "null" in the example) and the second argument is the sort clause. In the template you can then use <% control SortedFaculties %>

To get sorted child-pages in SiteTree I suggest the following:

public function SortedChildren(){
   $children = $this->Children();
   if(!$children)
      return null;
         
   $children->sort('DepartmentName', 'ASC');
   return $children;
}

Then in the template use <% control SortedChildren %> instead of <% Children %>

Avatar
Mohammed

Community Member, 25 Posts

2 February 2010 at 11:51pm

This works out great. Thanks a lot banal!

Is there a method of doing this without having to create children? For example, the CMS user clicks on the SiteTree "CollegeInformationPage" where they are able to input the Faculty's FirstName, Faculty's Lastname, and the Department they belong to.

Afterwards, the CMS will automatically group and sort all of the different Departments and displays the Name of the Department(sorted alphabetically) followed by the Faculty's FirstName and Lastname who belong to that Department(which are also sorted alphabetically).

Here's another example to help clarify:

Sample Data input via CMS:

(Department | FirstName Lastname)
Anatomy | Fred Cooks
Math | Jonny Alfords
Anatomy | Bart Deport
Zoology | Pikurt Adams
Anatomy | Lenny Yelisky
Math | Adam Zipper
Math | Matt Macking
Zoology | Escce Cocks
Zoology | Jonny Zypho

Desired output via Template:

Anatomy: Fred Cooks, Bart Deport, Lenny Yelisky
Math: Jonny Alfords, Matt Macking, Adam Zipper
Zoology: Pikurt Adams, Escce Cocks, Jonny Zypho

Any ideas if this is even possible?

Avatar
banal

Community Member, 901 Posts

3 February 2010 at 2:36am

Edited: 03/02/2010 2:36am

Yes, there are several ways to do this.
Here's an example that gathers all DataObjects and returns a new DataObjectSet that's suited for your use-case.

Setup:
A Page that has_many Person DataObjects. Each of these DataObjects has the Fields "Department", "Lastname" and "Firstname". The relation is called "Persons"

public function getDepartments(){
   // get all Persons in correct order
   $list = $this->Persons(null, 'Department, Lastname, Firstname');
   $data = array();
   $index = -1;
   $current = '';
   foreach($list as $item){
      if($item->Department != $current){
         ++$index;
         $current = $item->Department;
         $data[$index] = array(
            'Department' => $current,
            'Names' => array()
         );
      }
      
      $data[$index]['Names'][] = $item->Firstname . ' ' . $item->Lastname;
   }
   
   for($i = 0, $len = count($data); $i < $len; ++$i){
      $data[$i]['Names'] = implode(', ', $data[$i]['Names']);
   }
   
   return new DataObjectSet($data);
}

The above will build a sorted list of departments and the names that belong to it.
In the template you write something along these lines:

<% control Departments %>
<b>$Department:</b> $Names<br/>
<% end_control %>

Avatar
Mohammed

Community Member, 25 Posts

3 February 2010 at 5:13pm

Amazing. It works great! Thanks once again!

Here's what I ended up doing with the help of Community Member banal:

mysite/code/Staffdirectory.php

<?php

class Staffdirectory extends DataObject {

   static $db = array(
      'FirstName' => 'Text',
      'Lastname' => 'Text',
      'DepartmentName' => 'Text'
      );

   static $has_one = array(
      "StaffFacultyInfo" => "StaffFacultyInfo",
      );
   
function getCMSFields_forPopup() {
      $fields = new FieldSet();
      $fields->push( new TextField( 'FirstName', 'First Name' ) );
      $fields->push( new TextField( 'Lastname' ) );
      $fields->push( new TextField( 'DepartmentName' ) );
      return $fields;
      }
   }
class Staffdirectory_Controller extends Page_Controller {
   }
?>

I then created another file for the SiteTree.

mysite/code/StaffFacultyInfo.php

<?php

class StaffFacultyInfo extends Page {

static $has_many = array(
'Staffdirectories' => 'Staffdirectory'
    );

function getCMSFields() {
$fields = parent::getCMSFields();
    $fields->addFieldToTab("Root.Content.StaffInformation", new HasManyDataObjectManager(
$this,
'Staffdirectories',
'Staffdirectory',
array(
    'FirstName' => 'FirstName',
    'Lastname' => 'Lastname',
    'DepartmentName' => 'DepartmentName'
),
'getCMSFields_forPopup'
));
return $fields;
    }
   
   public function getDepartments(){
      // get all Persons in correct order
      $list = $this->Staffdirectories(null, 'DepartmentName, Lastname, FirstName');
      $data = array();
      $index = -1;
      $current = '';
      foreach($list as $item){
       if($item->DepartmentName != $current){
          ++$index;
          $current = $item->DepartmentName;
          $data[$index] = array(
            'Department' => $current,
            'Names' => array()
          );
       }
       $data[$index]['Names'][] = $item->FirstName . ' ' . $item->Lastname;
      }
      for($i = 0, $len = count($data); $i < $len; ++$i){
       $data[$i]['Names'] = implode(', ', $data[$i]['Names']);
      }
      return new DataObjectSet($data);
      }
   }

class StaffFacultyInfo_Controller extends Page_Controller {
   }
?>

This is what went into my template:

themes/mytheme/templates/Layout/StaffFacultyInfo.ss

<h2>$Title</h2>
$Content
      
      <div id="table">
         <% control Departments %>
         <div id="tableofinfo">
            <p class="nameofdepartment">$Department</p>
            <p class="nameofpeople">$Names</p>
         </div>
         <% end_control %>
      </div>
      
$Form
$PageComments

I hope this helps!