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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Customising the CMS /

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

Creating a shortcode that handles collections of data


Go to End


944 Views

Avatar
mjvezzani

Community Member, 5 Posts

25 May 2017 at 1:19am

Edited: 25/05/2017 1:21am

In my project I have a Feature class that extends DataObject. In Feature, I've defined a short code called `GetFeatureById`:

public static function GetFeatureById($arguments, $content = null, $parser = null, $tagName) {
    $id = (int)$arguments['id'];
    $feature = DataObject::get_by_id('Feature', $id);

    $arrayData = new ArrayData(array(
      'Title' => $feature->Title,
      'Content' => $feature->Description,
      'ImageURL' => $feature->Image()->url
    ));

    return $arrayData->renderWith('SingleFeatureTemplate');
  }

This short code retrieves a single Feature by providing an id, and it works as expected.
What I'm trying to do now is define a second shortcode `GetFeatures` that allows a user to pass in one to many parameters and renders 1 or more Features that match the parameters passed in. For example:

[get_features, section="foobar", limit=4]

would render a page of 4 Features that belong to the "foobar" section on the page. Here is the code I presently have to accomplish this:

public static function GetFeatures($arguments, $content = null, $parser = null, $tagName) {
    $limit = isset($arguments['limit']) ? (int)$arguments['limit'] : '';
    $filter = isset($arguments['section']) ? $arguments['section'] : '';
    $sort = isset($arguments['sort']) ? $arguments['sort'] : '';

    if ($filter == '') {
      $listOfFeatures = Feature::get()->sort($sort)->limit($limit);
    } else {
      $listOfFeatures = Feature::get()->filter(array('Section.Title' => $filter))->sort($sort)->limit($limit);
    }

    return $listOfFeatures->renderWith('MultipleFeatureTemplate');
  }

Here is my MultipleFeatureTemplate:

<% loop $Me %>
  <div class="col-md-4">
    <h3>$Title</h3>
    <p>$Description</h3>
  </div>
<% end_loop %>

This works just fine (except I have no clue why I have to use $Me in my template to get it to work, but whatever). However, I don't know how to get access to each Feature's image. The relationship between Feature and Image is `has_one`. In the GetFeatureById shortcode I'm explicitly setting the `$ImageURL` variable for use in the template. I'm not sure how to accomplish this with the GetFeatures shortcode, however. Trying the following:

<% loop $Me %>
  <div class="col-md-4">
    <img src=$Image->url />
    <h3>$Title</h3>
    <p>$Description</h3>
  </div>
<% end_loop %>

Results in properly displaying the Title and Description, but the url for the <img> does not get interpreted correctly. I have looked over the documentation for short codes multiple times and I haven't read anything that describes how to deal with rendering collections of DataObjects into a template that loops over that collection. Can anyone provide insight on how this might be done?