Silverstripe DataObjectSet and Templates

For some reason, I always forget how to generate a custom DataObjectSet in a Silverstripe method, that I can then return to my template to correctly render in a control loop. Because of this, I am going to write an example tutorial, using my Twitter RSS feed and SimpleXML (which should be part of the PHP5 core for most installs) as an example.

step 1: setting up your model and controller.

In this tutorial, I am going to add my Twitter feed to my Page class. That way it can appear on all pages, and be available to child classes as well.

To do this I will first add a TwitterURL field to my model, as well as the relevant fields to the CMS:


class Page extends SiteTree {
 static $db = array(
  'TwitterURL'=> 'Text'
);

public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Content.Misc',new TextField('TwitterURL', 'Twitter URL'));
return $fields;
}
}

Next, I will add the method I will call in my template to my controller:


class Page_Controller extends ContentController {
public function init() {
parent::init();
}

public function getTwitterFeed($limit = 5) {
// More to go here
}
}

step 2: getting our rss feed. 

Now the basic setup is complete, now we need to write some code to extract our Twitter feed and then loop through each posted item in the feed channel. Here is how we would do this using SimpleXML (there are other methods of doing something similar, including PHP Dom and SimplePie):


class Page_Controller extends ContentController {
...

public function getTwitterFeed($limit = 5) {
$Twitter = simplexml_load_file($this->TwitterURL);
$i = 0;

foreach($Twitter->channel->item as $item) {
if($i < $limit) {
// Some data object stuff will go here shortly
}
}
}
}

Admitidly this wont do much at the moment, just loop through the items in your RSS feed until you the end, or the loop reaches the limit set by $limit.

step 3: setting up our dataobjectset

Now we have our loop, the interesting bit can begin. Now we need to create a new DataObjectSet and for each item, push an array of data to it. This will be the data that is then sent to the template for rendering.

Now you need to alter your getTwitterFeed() method as below:


class Page_Controller extends ContentController {
...

public function getTwitterFeed($limit = 5) {
$Twitter = simplexml_load_file($this->TwitterURL);
$result = new DataObjectSet();
$i = 0;

foreach($Twitter->channel->item as $item) {
if($i < $limit) {
// To retrieve the publish date in a format that Silverstripe
// will be able to play with, we need to convert it to a date object.
$Date = new Date('Date');
$Date->setValue((string)$item->pubDate);

// Put info from RSS into an Array, then push into $result
$result->push(new ArrayData(array(
'Title' => (string)$item->title,
'Date' => $Date
)));

$i++;
}
}

return $result;
}
}

Now what is happening is that we create a new DataObjectSet called $result. For each iteration of the RSS feed, we take the title and date from the feed, convert and cast then as necessary then put that into an array. Silverstripe requires that this data be formatted using an ArrayData object, so we use that first, before dding the data to our DataObjectSet.

Finally we return the completed DataObjectSet, from this example, the variables $Title and $Date will be available in your control loop.

step 4: setting up your template.

Now we have all the data in in right format, the final step is to render it in your template. In order to render each tweet as a paragraph, you would do:


<% control getTwitterFeed %>
  <p>
    $Title<br/>
    Posted: $Date.Ago
  </p>
<% end_control %>

By default, this method will display the 5 most recent tweets. If you wanted to show a different number, for example 10, you could use:


<% control getTwitterFeed(10) %>
<p>
$Title<br/>
Posted: $Date.Ago
</p>
<% end_control %>

Thats it, if you want to include additional info, like Link and Description, you simply have to add those items to your array in your method. These will then be available to you in your template.

go back

call 01594 860082, email or  get a quote