4 permalink: view_templates.html
9 Templates are responsible for the output a user sees when requesting a page (while the PHP code is responsible for providing the data that will be shown).
10 Templates are text files with `.tpl` as the file extension.
11 WoltLab Suite Core compiles the template files once into a PHP file that is executed when a user requests the page.
12 In subsequent request, as the PHP file containing the compiled template already exists, compiling the template is not necessary anymore.
15 ## Template Types and Conventions
17 WoltLab Suite Core supports two types of templates:
18 frontend templates (or simply *templates*) and backend templates (*ACP templates*).
19 Each type of template is only available in its respective domain, thus frontend templates cannot be included or used in the ACP and vice versa.
21 For pages and forms, the name of the template matches the unqualified name of the PHP class except for the `Page` or `Form` suffix:
23 - `RegisterForm.class.php` → `register.tpl`
24 - `UserPage.class.php` → `user.tpl`
26 If you follow this convention, WoltLab Suite Core will automatically determine the template name so that you do not have to explicitly set it.
28 {% include callout.html content="For forms that handle creating and editing objects, in general, there are two form classes: `FooAddForm` and `FooEditForm`. WoltLab Suite Core, however, generally only uses one template `fooAdd.tpl` and the template variable `$action` to distinguish between creating a new object (`$action = 'add'`) and editing an existing object (`$action = 'edit'`) as the differences between templates for adding and editing an object are minimal." type="info" %}
32 ## Installing Templates
34 Templates and ACP templates are installed by two different package installation plugins:
35 the [template PIP](package_pip_template.md) and the [ACP template PIP](package_pip_acp-template.md).
36 More information about installing templates can be found on those pages.
44 {include file='header'}
48 {include file='footer'}
54 {include file='header' pageTitle='foo.bar.baz'}
56 <header class="contentHeader">
57 <div class="contentHeaderTitle">
58 <h1 class="contentTitle">Title</h1>
61 <nav class="contentHeaderNavigation">
63 {* your default content header navigation buttons *}
65 {event name='contentHeaderNavigation'}
72 {include file='footer'}
75 `foo.bar.baz` is the language item that contains the title of the page.
78 ## Common Template Components
82 {% include callout.html content="For new forms, use the new [form builder API](php_api_form_builder.md) introduced with WoltLab Suite 5.2." type="info" %}
85 <form method="post" action="{link controller='FooBar'}{/link}">
87 <dl{if $errorField == 'baz'} class="formError"{/if}>
88 <dt><label for="baz">{lang}foo.bar.baz{/lang}</label></dt>
90 <input type="text" id="baz" name="baz" value="{$baz}" class="long" required autofocus>
91 {if $errorField == 'baz'}
92 <small class="innerError">
93 {if $errorType == 'empty'}
94 {lang}wcf.global.form.error.empty{/lang}
96 {lang}foo.bar.baz.error.{@$errorType}{/lang}
104 <dt><label for="bar">{lang}foo.bar.bar{/lang}</label></dt>
106 <textarea name="bar" id="bar" cols="40" rows="10">{$bar}</textarea>
107 {if $errorField == 'bar'}
108 <small class="innerError">{lang}foo.bar.bar.error.{@$errorType}{/lang}</small>
115 {event name='dataFields'}
120 {event name='sections'}
122 <div class="formSubmit">
123 <input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
132 <div class="section tabMenuContainer">
133 <nav class="tabMenu">
135 <li><a href="{@$__wcf->getAnchor('tab1')}">Tab 1</a></li>
136 <li><a href="{@$__wcf->getAnchor('tab2')}">Tab 2</a></li>
138 {event name='tabMenuTabs'}
142 <div id="tab1" class="tabMenuContent">
143 <div class="section">
144 {* contents of first tab *}
148 <div id="tab2" class="tabMenuContainer tabMenuContent">
151 <li><a href="{@$__wcf->getAnchor('tab2A')}">Tab 2A</a></li>
152 <li><a href="{@$__wcf->getAnchor('tab2B')}">Tab 2B</a></li>
154 {event name='tabMenuTab2Subtabs'}
158 <div id="tab2A" class="tabMenuContent">
159 <div class="section">
160 {* contents of first subtab for second tab *}
164 <div id="tab2B" class="tabMenuContent">
165 <div class="section">
166 {* contents of second subtab for second tab *}
170 {event name='tabMenuTab2Contents'}
173 {event name='tabMenuContents'}
178 ## Template Scripting
180 ### Template Variables
182 Template variables can be assigned via `WCF::getTPL()->assign('foo', 'bar')` and accessed in templates via `$foo`:
184 - `{$foo}` will result in the contents of `$foo` to be passed to `StringUtil::encodeHTML()` before being printed.
185 - `{#$foo}` will result in the contents of `$foo` to be passed to `StringUtil::formatNumeric()` before being printed.
186 Thus, this method is relevant when printing numbers and having them formatted correctly according the the user’s language.
187 - `{@$foo}` will result in the contents of `$foo` to be printed directly.
188 In general, this method should not be used for user-generated input.
190 Multiple template variables can be assigned by passing an array:
193 WCF::getTPL()->assign([
201 If you want to call a function on a variable, you can use the modifier syntax:
202 `{@$foo|trim}`, for example, results in the trimmed contents of `$foo` to be printed.
204 #### System Template Variable
206 The template variable `$tpl` is automatically assigned and is an array containing different data:
208 - `$tpl[get]` contains `$_GET`.
209 - `$tpl[post]` contains `$_POST`.
210 - `$tpl[cookie]` contains `$_COOKIE`.
211 - `$tpl[server]` contains `$_SERVER`.
212 - `$tpl[env]` contains `$_ENV`.
213 - `$tpl[now]` contains `TIME_NOW` (current timestamp).
215 Furthermore, the following template variables are also automatically assigned:
217 - `$__wcf` contains the `WCF` object (or `WCFACP` object in the backend).
221 Comments are wrapped in `{*` and `*}` and can span multiple lines:
228 {% include callout.html content="The template compiler discards the comments, so that they not included in the compiled template." type="info" %}
232 Conditions follow a similar syntax to PHP code:
237 {elseif $foo === 'baz'}
240 foo is neither bar nor baz
244 The supported operators in conditions are `===`, `!==`, `==`, `!=`, `<=`, `<`, `>=`, `>`, `||`, `&&`, `!`, and `=`.
249 {if $bar|isset}…{/if}
251 {if $bar|count > 3 && $bar|count < 100}…{/if}
256 Foreach loops allow to iterate over arrays or iterable objects:
260 {foreach from=$array key=key item=value}
261 <li>{$key}: {$value}</li>
266 While the `from` attribute containing the iterated structure and the `item` attribute containg the current value are mandatory, the `key` attribute is optional.
267 If the foreach loop has a name assigned to it via the `name` attribute, the `$tpl` template variable provides additional data about the loop:
271 {foreach from=$array key=key item=value name=foo}
272 {if $tpl[foreach][foo][first]}
273 something special for the first iteration
274 {elseif $tpl[foreach][foo][last]}
275 something special for the last iteration
278 <li>iteration {#$tpl[foreach][foo][iteration]+1} out of {#$tpl[foreach][foo][total]} {$key}: {$value}</li>
283 In contrast to PHP’s foreach loop, templates also support `foreachelse`:
286 {foreach from=$array item=value}
289 there is nothing to iterate over
293 ### Including Other Templates
295 To include template named `foo` from the same domain (frontend/backend), you can use
301 If the template belongs to an application, you have to specify that application using the `application` attribute:
304 {include file='foo' application='app'}
307 Additional template variables can be passed to the included template as additional attributes:
310 {include file='foo' application='app' var1='foo1' var2='foo2'}
315 An overview of all available template plugins can be found [here](view_template-plugins.md).