Version 3 end of life
This version of Silverstripe CMS will not recieve any additional bug fixes or documentation updates. Go to documentation for the most recent stable version.

Template Syntax

SilverStripe templates are plain text files that have .ss extension and located within the templates directory of a module, theme, or your mysite folder. A template can contain any markup language (e.g HTML, CSV, JSON..) and before being rendered to the user, they're processed through SSViewer. This process replaces placeholders such as $Var with real content from your model and allows you to define logic controls like <% if $Var %>.

An example of a SilverStripe template is below:

mysite/templates/Page.ss

	<html>
		<head>
			<% base_tag %>
			<title>$Title</title>
			<% require themedCSS("screen") %>
		</head>
		<body>
			<header>
				<h1>Bob's Chicken Shack</h1>
			</header>

			<% with $CurrentMember %>
				<p>Welcome $FirstName $Surname.</p>
			<% end_with %>

			<% if $Dishes %>
			<ul>
				<% loop $Dishes %>
					<li>$Title ($Price.Nice)</li>
				<% end_loop %>
			</ul>
			<% end_if %>

			<% include Footer %>
		</body>
	</html>

Templates can be used for more than HTML output. You can use them to output your data as JSON, XML, CSV or any other text-based format. [/note]

Variables

Variables are placeholders that will be replaced with data from the DataModel or the current Controller. Variables are prefixed with a $ character. Variable names must start with an alphabetic character or underscore, with subsequent characters being alphanumeric or underscore:

	$Title

Variables can be chained together, and include arguments.

	$Foo
	$Foo(param)
	$Foo.Bar
  • $Foo will call $obj->Foo() (or the field $obj->Foo)
  • $Foo(param) will call $obj->Foo("param")
  • $Foo.Bar will call $obj->Foo()->Bar()

If a variable returns a string, that string will be inserted into the template. If the variable returns an object, then the system will attempt to render the object through its forTemplate() method. If the forTemplate() method has not been defined, the system will return an error.

[note] For more detail around how variables are inserted and formatted into a template see Formating, Modifying and Casting Variables [/note]

Variables can come from your database fields, or custom methods you define on your objects.

mysite/code/Page.php

	public function UsersIpAddress() {
		return $this->getRequest()->getIP();
	}
	<p>You are coming from $UsersIpAddress.</p>
	Method names that begin with `get` will automatically be resolved when their prefix is excluded. For example, the above method call `$UsersIpAddress` would also invoke a method named `getUsersIpAddress()`.

The variables that can be used in a template vary based on the object currently in scope. Scope defines what object the methods get called on. For the standard Page.ss template the scope is the current Page_Controller class. This object gives you access to all the database fields on Page_Controller, its corresponding Page record and any subclasses of those two.

mysite/code/Layout/Page.ss

	$Title
	// returns the page `Title` property

	$Content
	// returns the page `Content` property

Conditional Logic

The simplest conditional block is to check for the presence of a value (does not equal 0, null, false).

	<% if $CurrentMember %>
		<p>You are logged in as $CurrentMember.FirstName $CurrentMember.Surname.</p>
	<% end_if %>

A conditional can also check for a value other than falsy.

	<% if $MyDinner == "kipper" %>
		Yummy, kipper for tea.
	<% end_if %>
	

[notice] When inside template tags variables should have a '$' prefix, and literals should have quotes. [/notice]

Conditionals can also provide the else case.

	<% if $MyDinner == "kipper" %>
		Yummy, kipper for tea
	<% else %>
		I wish I could have kipper :-(
	<% end_if %>
	<% if $MyDinner == "quiche" %>
		Real men don't eat quiche
	<% else_if $MyDinner == $YourDinner %>
		We both have good taste
	<% else %>
		Can I have some of your chips?
	<% end_if %>

The inverse of <% if %> is <% if not %>.

	<% if not $DinnerInOven %>
		I'm going out for dinner tonight.
	<% end_if %>

Multiple checks can be done using ||, or, && or and.

If either of the conditions is true.

	<% if $MyDinner == "kipper" || $MyDinner == "salmon" %>
		yummy, fish for tea
	<% end_if %>
	<% if $MyDinner == "quiche" && $YourDinner == "kipper" %>
		Lets swap dinners
	<% end_if %>

You can use inequalities like <, <=, >, >= to compare numbers.

	<% if $Number >= "5" && $Number <= "10" %>
		Number between 5 and 10
	<% end_if %>

Includes

Within SilverStripe templates we have the ability to include other templates from the template/Includes directory using the <% include %> tag.

	<% include SideBar %>

the include only happens if the user is logged in.

	<% if $CurrentMember %>
		<% include MembersOnlyInclude %>
	<% end_if %>

include.

	<% with $CurrentMember %>
		<% include MemberDetails Top=$Top, Name=$Name %>
	<% end_with %>

Looping Over Lists

The <% loop %> tag is used to iterate or loop over a collection of items such as DataList or a ArrayList collection.

	<h1>Children of $Title</h1>

	<ul>
		<% loop $Children %>
			<li>$Title</li>
		<% end_loop %>
	</ul>

page.

[notice] $Title inside the loop refers to the Title property on each object that is looped over, not the current page like the reference of $Title outside the loop.

This demonstrates the concept of Scope. When inside a <% loop %> the scope of the template has changed to the object that is being looped over. [/notice]

Altering the list

<% loop %> statements iterate over a DataList instance. As the template has access to the list object, templates can call DataList methods.

Sorting the list by a given field.

	<ul>
		<% loop $Children.Sort(Title, ASC) %>
			<li>$Title</li>
		<% end_loop %>
	</ul>
	<ul>
		<% loop $Children.Limit(10) %>
			<li>$Title</li>
		<% end_loop %>
	</ul>
	<ul>
		<% loop $Children.Reverse %>
			<li>$Title</li>
		<% end_loop %>
	</ul>
	<ul>
		<% loop $Children.Filter('School', 'College') %>
			<li>$Title</li>
		<% end_loop %>
	</ul>
	<ul>
		<% loop $Children.Filter('School', 'College').Sort(Score, DESC) %>
			<li>$Title</li>
		<% end_loop %>
	</ul>

Inside the loop scope, there are many variables at your disposal to determine the current position in the list and iteration.

  • $Even, $Odd: Returns boolean, handy for zebra striping.
  • $EvenOdd: Returns a string, either 'even' or 'odd'. Useful for CSS classes.
  • $First, $Last, $Middle: Booleans about the position in the list.
  • $FirstLast: Returns a string, "first", "last", "first last" (if both), or "". Useful for CSS classes.
  • $Pos: The current position in the list (integer). Will start at 1, but can take a starting index as a parameter.
  • $FromEnd: The position of the item from the end (integer). Last item defaults to 1, but can be passed as a parameter.
  • $TotalItems: Number of items in the list (integer).
	<ul>
		<% loop $Children.Reverse %>
			<% if First %>
				<li>My Favourite</li>
			<% end_if %>

			<li class="$EvenOdd">Child $Pos of $TotalItems - $Title</li>
		<% end_loop %>
	</ul>

A common task is to paginate your lists. See the Pagination how to for a tutorial on adding pagination. [/info]

Modulus and MultipleOf

$Modulus and $MultipleOf can help to build column and grid layouts.

	// returns an int
	$Modulus(value, offset)

	// returns a boolean.
	$MultipleOf(factor, offset) 

	<% loop $Children %>
	<div class="column-{$Modulus(4)}">
		...
	</div>
	<% end_loop %>

	// returns <div class="column-3">, <div class="column-2">,

$Modulus is useful for floated grid CSS layouts. If you want 3 rows across, put $Modulus(3) as a class and add a clear: both to .column-1. [/hint]

$MultipleOf(value, offset) can also be utilized to build column and grid layouts. In this case we want to add a <br> after every 3rd item.

	<% loop $Children %>
		<% if $MultipleOf(3) %>
			<br>
		<% end_if %>
	<% end_loop %>

Sometimes you will have template tags which need to roll into one another. Use {} to contain variables.

	$Foopx // will returns "" (as it looks for a `Foopx` value)
	{$Foo}px  // returns "3px" (CORRECT)

Or when having a $ sign in front of the variable such as displaying money.

	$$Foo // returns ""
	${$Foo} // returns "$3"
	$Foo // returns "3"
	\$Foo // returns "$Foo"

For more information on formatting and casting variables see Formating, Modifying and Casting Variables [/hint]

Scope

In the <% loop %> section, we saw an example of two scopes. Outside the <% loop %>...<% end_loop %>, we were in the scope of the top level Page. But inside the loop, we were in the scope of an item in the list (i.e the Child)

The scope determines where the value comes from when you refer to a variable. Typically the outer scope of a Page.ss layout template is the Page_Controller that is currently being rendered.

When the scope is a Page_Controller it will automatically also look up any methods in the corresponding Page data record. In the case of $Title the flow looks like

	$Title --> [Looks up: Current Page_Controller and parent classes] --> [Looks up: Current Page and parent classes]

classes of the current scope object, and any Extension instances you have.

Navigating Scope

Up

When in a particular scope, $Up takes the scope back to the previous level.

	<h1>Children of '$Title'</h1>

	<% loop $Children %>
		<p>Page '$Title' is a child of '$Up.Title'</p>
	
		<% loop $Children %>
			<p>Page '$Title' is a grandchild of '$Up.Up.Title'</p>
		<% end_loop %>
	<% end_loop %>
	My Page
	|
	+-+ Child 1

| +- Grandchild 1 | +-+ Child 2

	Children of 'My Page'

	Page 'Child 1' is a child of 'My Page'
	Page 'Grandchild 1' is a grandchild of 'My Page'
	Page 'Child 2' is a child of 'MyPage'

Additional selectors implicitely change the scope so you need to put additional $Up to get what you expect. [/notice]

	<h1>Children of '$Title'</h1>
	<% loop $Children.Sort('Title').First %>
		<%-- We have two additional selectors in the loop expression so... --%> 
		<p>Page '$Title' is a child of '$Up.Up.Up.Title'</p>
	<% end_loop %>

While $Up provides us a way to go up one level of scope, $Top is a shortcut to jump to the top most scope of the page. The previous example could be rewritten to use the following syntax.

	<h1>Children of '$Title'</h1>

	<% loop $Children %>
		<p>Page '$Title' is a child of '$Top.Title'</p>
	
		<% loop $Children %>
			<p>Page '$Title' is a grandchild of '$Top.Title'</p>
		<% end_loop %>
	<% end_loop %>

The <% with %> tag lets you change into a new scope. Consider the following example:

	<% with $CurrentMember %>
		Hello, $FirstName, welcome back. Your current balance is $Balance.
	<% end_with %>
	Hello, $CurrentMember.FirstName, welcome back. Your current balance is $CurrentMember.Balance

Outside the <% with %>., we are in the page scope. Inside it, we are in the scope of $CurrentMember object. We can refer directly to properties and methods of the Member object. $FirstName inside the scope is equivalent to $CurrentMember.FirstName.

Me

$Me outputs the current object in scope. This will call the forTemplate of the object.

	$Me

Using standard HTML comments is supported. These comments will be included in the published site.

	$EditForm <!-- Some public comment about the form -->

However you can also use special SilverStripe comments which will be stripped out of the published site. This is useful for adding notes for other developers but for things you don't want published in the public html.

	$EditForm <%-- Some hidden comment about the form --%>
Rendering data to a template
Call and render SilverStripe templates manually.
Requirements
How to include and require other assets in your templates such as javascript and CSS files.
Common Variables
Some of the common variables and methods your templates can use, including Menu, SiteConfig, and more.
Template Syntax
A look at the operations, variables and language controls you can use within templates.
Template Inheritance
Override and extend module and core markup templates from your application code.
Themes
What makes up a SilverStripe Theme. How to install one or write your own theme.
Caching
Reduce rendering time with cached templates and understand the limitations of the ViewableData object caching.
Formatting, Modifying and Casting Variables
Information on casting, security, modifying data before it's displayed to the user and how to format data within the template.
Translations
Definition of the syntax for writing i18n compatible templates.
How To's

How to's

Rendering data to a template
Call and render SilverStripe templates manually.
Requirements
How to include and require other assets in your templates such as javascript and CSS files.
Common Variables
Some of the common variables and methods your templates can use, including Menu, SiteConfig, and more.
Template Syntax
A look at the operations, variables and language controls you can use within templates.
Template Inheritance
Override and extend module and core markup templates from your application code.
Themes
What makes up a SilverStripe Theme. How to install one or write your own theme.
Caching
Reduce rendering time with cached templates and understand the limitations of the ViewableData object caching.
Formatting, Modifying and Casting Variables
Information on casting, security, modifying data before it's displayed to the user and how to format data within the template.
Translations
Definition of the syntax for writing i18n compatible templates.
How To's

API Documentation