Jump to:

3460 Posts in 1064 Topics by 739 members

Data Model Questions

SilverStripe Forums » Data Model Questions » Pagination of a Has_Many element

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1
Go to End
Author Topic: 1370 Views
  • KINKCreative
    Community Member
    56 Posts

    Pagination of a Has_Many element Link to this post

    I have been searching all references and been trying the DataObjectModel examples for pagination until I realized that a has_many reference isn't part of the DOM scope. Duh.

    Sorry to be "lazy", I've spent about 3 days on this now, loved the challenge of trying to crack it, but now I am just tired. Here's what I am trying to do.

    class ProfileListPage extends Page {
       static $db = array(
       static $has_one = array(
       static $has_many = array(
          'Performers' => 'ProfileListProfile'
       public function getCMSFields()
          $f = parent::getCMSFields();

          $performerManager = new DataObjectManager(
             $this, // Controller
             'Performers', // Source name
             'ProfileListProfile', // Source class
                'Name' => 'Name',
                'LastName' => 'LastName',
                'Location' => 'Location',
                'Sex' => 'Sex',
                'Styles' => 'Styles',
                'CV' => 'CV',
                'About' => 'About',
                'Thumbnail' => 'Image',
                'Links' => 'ProfileListLink'
              'LastName ASC'


    The underlying ProfileListProfile class is here:

    class ProfileListProfile extends DataObject
       static $db = array (
          'Name' => 'Text',
          'LastName' => 'Text',
          'Location' => 'Text',
          'Sex' => "Enum('Male, Female', 'Female')",
          'Styles' => 'Text',
          'CV' => 'Text',
          'About' => 'Text'
       static $has_one = array (
          'Image' => 'Image',
          'Page' => 'ProfileListPage'
       static $has_many = array (
          'Links' => 'ProfileListLink'
       function Thumbnail() {
          $Image = $this->Image();
          if ( $Image ) {
             return $Image->CMSThumbnail();
          } else {
             return null;
       static $default_sort = "LastName ASC";
       public function getCMSFields_forPopup()
          return new FieldSet(
             new TextField('Name'),
             new TextField('LastName'),
             new DropdownField('Sex', 'Choose', singleton('ProfileListProfile')->dbObject('Sex')->enumValues()),
             new TextField('Location'),
             new TextAreaField('Styles'),
             new TextAreaField('CV'),
             new SimpleImageField('Image','Profile Picture',null,null,null,'ProfilePhotos'),
             new DataObjectManager ($this, 'Links', 'ProfileListLink', array('Title'=>'Link Name', 'Link' => 'URL'))

    Now... On a given ProfileListPage there should display a limited number (8) subset of Performers. The template sees $this->Performers properly, but I just need a subset. I am not good enough with the Silverstripe database queries and dataset casting to figure out how on a given page I can have e.g. a CurrentSet which will include the records from 0-7 if no argument is passed to the page. If a page argument is somehow passed, the next 8 - and so on - will display. I wasn't even sure whether I'd need to create a special action on the page (how would a CurrentSet function otherwise receive the page argument?). Sorry for requesting to be babied, but I'm really stuck here Thanks.

  • MarcusDalgren
    Community Member
    288 Posts

    Re: Pagination of a Has_Many element Link to this post

    One babying coming up!

    I'm assuming that you want to paginate when displaying on the frontend through one of your templates.
    What you have to do is write a custom getter in your ProfileListPage that takes pagination into account. There's an article about pagination here but I'm going to walk you through it for this specific case.

    So let's call your function getPaginatedPerformers (a rip from the recipe but modified slightly for your case)

    function getPaginatedPerformers() {
    if(!isset($_GET['start']) || !is_numeric($_GET['start']) || (int)$_GET['start'] < 1) $_GET['start'] = 0;
    $SQL_start = (int)$_GET['start'];
    $doSet = DataObject::get(
    $callerClass = "ProfileListProfile",
    $filter = "`PageID` = '".$this->ID."'",
    $sort = "",
    $join = "",
    $limit = "{$SQL_start},8"

    return $doSet ? $doSet : false;

    Now you can call this function in your templates through <% control PaginatedPerformers %> note that we leave out "get" when calling model functions in the template. Put anything you want within the control and then after that you add your pagination controls. They can look like this for example (ripped from the recipe but with your variable names)

    <% if PaginatedPerformers.MoreThanOnePage %>
    <% if PaginatedPerformers.PrevLink %>
    <a href="$PaginatedPerformers.PrevLink">&lt;&lt; Prev</a> |
    <% end_if %>

    <% control PaginatedPerformers.Pages %>
    <% if CurrentBool %>
    <% else %>
    <a href="$Link" title="Go to page $PageNum">$PageNum</a>
    <% end_if %>
    <% end_control %>

    <% if PaginatedPerformers.NextLink %>
    | <a href="$PaginatedPerformers.NextLink">Next &gt;&gt;</a>
    <% end_if %>
    <% end_if %>

    Try this out and let me know if it works!

  • KINKCreative
    Community Member
    56 Posts

    Re: Pagination of a Has_Many element Link to this post

    Amazing, that worked like a charm. I didn't even realize you could just pass the page variable via url, thought I'd have to rely on actions and ID's. That "get-" prefix for e.g. getPaginatedPerformers vs PaginatedPerformers in the template, I never knew that was possible / necessary. Thank you so much!

Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.