如何在silverstripe中循环模板

Hello,

I'm doing a one-page site in silverstripe and i have created some templates that will represent my different site parts.

I first tried to loop by using 'include' so :

<% if SlugItems %>
    <% loop SlugItems %>
        <% include $slug %>
    <% end_loop %>
<% end_if %>

But from what i found on forums, it's not the way to do it and i got an error with loop tag missing...So i tried to create a function

public function IncludeTemplate($template) {
    return $this->renderWith($template);
}

And

<% if SlugItems %>
    <% loop SlugItems %>
        <% IncludeTemplate($Slug) %>
    <% end_loop %>
<% end_if %>

Big surprise...It's the same, cause i read that both include and renderWith do the same job. Well, i don't really know a good solution and i'd like to implement something more elaborate than including some template if my template name is like X, eg.

<% if $ClassName = 'SomeClass' %>
    <% include SomeClass %> 
<% else_if $ClassName = 'SomeOtherClass' %>
    <% include SomeOtherClass %>
<% else %>
    <% include DefaultClass %>
<% end_if %>

If you know a good solution, please write it here! That would make my day :D.

Thanks, Thomas

What it sounds like you are trying to do is similar to a module called Content Blocks.

In that module, they have an identical situation where they loop over blocks and insert the right template for that block.

The module's Page.ss:

<% loop $ActiveBlocks %>$Me<% end_loop %>

$ActiveBlocks refers to a function on a DataExtension by the same name.

This is all stuff that you are already familiar with. The part that you might not know so much about is the $Me value in the template. It can be used to refer to the current object context the template is rendered with, in your case that would be a Slug.

That is only part of the magic, the other part is a function on the Block DataObject the called forTemplate. This is called when using $Me to work out how to render the DataObject.

In here, you can just perform a classic renderWith call like this:

return $this->renderWith(array($this->Template, 'Slug'));

With this knowledge, you could achieve what you are after by having a Slug DataObject looking something like this:

class Slug extends DataObject
{
    static $db = array();

    function getTemplate()
    {
        $template = 'yourTemplate';

        //Do your template logic checks in here to work out what you want to display

        return $template;
    }

    function forTemplate()
    {
        return $this->renderWith(array($this->Template, 'Slug'));
    }
}

With your template looking something like this:

<% if $Slugs %>
    <% loop $Slugs %>
        $Me
    <% end_loop %>
<% end_if %>

You can define a template file, say Slug.ss, where you put the HTML you want to loop over, and save it into themes/your-theme/templates/Includes.

Then you can just loop over it with this code:

<% if SlugItems %>
    <% loop SlugItems %>
        <% include Slug %>
    <% end_loop %>
<% end_if %>

i did something similar in my onepage module

try something like that:

    /**
    * renders the current page using the ClassName_onepage template,
    * e.g. Page_onepage
    *
    * @return HTMLText
    */
    public function getOnePageContent(){
    $templateName = SSViewer::get_templates_by_class($this->owner->Classname, '_onepage', 'SiteTree')
    ?: 'Page_onepage';
    return $this->renderWith($templateName);
    }

And in your template:

    <% if SlugItems %>
        <% loop SlugItems %>
            $OnePageContent
        <% end_loop %>
    <% end_if %>

HTH,

wmk