Upgrade from Smarty 3 to Smarty 4 to be PHP 8.1 compatible

Remove all Smarty4 dedicated tests, all are done in the same test file
like before
This commit is contained in:
Clemens Schwaighofer
2022-04-06 15:12:50 +09:00
parent 4b0e9b44c3
commit f8ee6044f9
478 changed files with 33447 additions and 12496 deletions
@@ -0,0 +1,49 @@
{append} {#language.function.append}
========
`{append}` is used for creating or appending template variable arrays
**during the execution of a template**.
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ----------------------------------------------------------------------------------------------------
var string Yes *n/a* The name of the variable being assigned
value string Yes *n/a* The value being assigned
index string No *n/a* The index for the new array element. If not specified the value is append to the end of the array.
scope string No *n/a* The scope of the assigned variable: \'parent\',\'root\' or \'global\'
**Option Flags:**
Name Description
--------- -----------------------------------------------------
nocache Assigns the variable with the \'nocache\' attribute
{append var='name' value='Bob' index='first'}
{append var='name' value='Meyer' index='last'}
// or
{append 'name' 'Bob' index='first'} {* short-hand *}
{append 'name' 'Meyer' index='last'} {* short-hand *}
The first name is {$name.first}.<br>
The last name is {$name.last}.
The above example will output:
The first name is Bob.
The last name is Meyer.
See also [`append()`](#api.append) and
[`getTemplateVars()`](#api.get.template.vars).
@@ -0,0 +1,149 @@
{assign} {#language.function.assign}
========
`{assign}` is used for assigning template variables **during the
execution of a template**.
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
> **Note**
>
> See also the [`short-form`](#language.function.shortform.assign)
> method of assigning template vars.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- -----------------------------------------------------------------------
var string Yes *n/a* The name of the variable being assigned
value string Yes *n/a* The value being assigned
scope string No *n/a* The scope of the assigned variable: \'parent\',\'root\' or \'global\'
**Option Flags:**
Name Description
--------- -----------------------------------------------------
nocache Assigns the variable with the \'nocache\' attribute
{assign var="name" value="Bob"}
{assign "name" "Bob"} {* short-hand *}
The value of $name is {$name}.
The above example will output:
The value of $name is Bob.
{assign var="name" value="Bob" nocache}
{assign "name" "Bob" nocache} {* short-hand *}
The value of $name is {$name}.
The above example will output:
The value of $name is Bob.
{assign var=running_total value=$running_total+$some_array[$row].some_value}
Variables assigned in the included template will be seen in the
including template.
{include file="sub_template.tpl"}
...
{* display variable assigned in sub_template *}
{$foo}<br>
...
The template above includes the example `sub_template.tpl` below
...
{* foo will be known also in the including template *}
{assign var="foo" value="something" scope=parent}
{* bar is assigned only local in the including template *}
{assign var="bar" value="value"}
...
You can assign a variable to root of the current root tree. The variable
is seen by all templates using the same root tree.
{assign var=foo value="bar" scope="root"}
A global variable is seen by all templates.
{assign var=foo value="bar" scope="global"}
{assign "foo" "bar" scope="global"} {* short-hand *}
To access `{assign}` variables from a php script use
[`getTemplateVars()`](#api.get.template.vars). Here\'s the template that
creates the variable `$foo`.
{assign var="foo" value="Smarty"}
The template variables are only available after/during template
execution as in the following script.
<?php
// this will output nothing as the template has not been executed
echo $smarty->getTemplateVars('foo');
// fetch the template to a variable
$whole_page = $smarty->fetch('index.tpl');
// this will output 'smarty' as the template has been executed
echo $smarty->getTemplateVars('foo');
$smarty->assign('foo','Even smarter');
// this will output 'Even smarter'
echo $smarty->getTemplateVars('foo');
?>
The following functions can also *optionally* assign template variables.
[`{capture}`](#language.function.capture),
[`{include}`](#language.function.include),
[`{include_php}`](#language.function.include.php),
[`{insert}`](#language.function.insert),
[`{counter}`](#language.function.counter),
[`{cycle}`](#language.function.cycle),
[`{eval}`](#language.function.eval),
[`{fetch}`](#language.function.fetch),
[`{math}`](#language.function.math),
[`{textformat}`](#language.function.textformat)
See also [`{$var=...}`](#language.function.shortform.assign),
[`assign()`](#api.assign) and
[`getTemplateVars()`](#api.get.template.vars).
@@ -0,0 +1,191 @@
{block} {#language.function.block}
=======
`{block}` is used to define a named area of template source for template
inheritance. For details see section of [Template
Interitance](#advanced.features.template.inheritance).
The `{block}` template source area of a child template will replace the
correponding areas in the parent template(s).
Optionally `{block}` areas of child and parent templates can be merged
into each other. You can append or prepend the parent `{block}` content
by using the `append` or `prepend` option flag with the childs `{block}`
definition. With the {\$smarty.block.parent} the `{block}` content of
the parent template can be inserted at any location of the child
`{block}` content. {\$smarty.block.child} inserts the `{block}` content
of the child template at any location of the parent `{block}`.
`{blocks}'s` can be nested.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ---------------------------------------
name string Yes *n/a* The name of the template source block
**Option Flags (in child templates only):**
Name Description
--------- -------------------------------------------------------------------------------------------
append The `{block}` content will be be appended to the content of the parent template `{block}`
prepend The `{block}` content will be prepended to the content of the parent template `{block}`
hide Ignore the block content if no child block of same name is existing.
nocache Disables caching of the `{block}` content
parent.tpl
<html>
<head>
<title>{block name="title"}Default Title{/block}</title>
<title>{block "title"}Default Title{/block}</title> {* short-hand *}
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Page Title</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}Title - {/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title" prepend}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Title - Page Title</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"} is my title{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title" append}
Page Title
{/block}
The result would look like
<html>
<head>
<title>Page title is my titel</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}The {$smarty.block.child} was inserted here{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
Child Title
{/block}
The result would look like
<html>
<head>
<title>The Child Title was inserted here</title>
</head>
</html>
parent.tpl
<html>
<head>
<title>{block name="title"}Parent Title{/block}</title>
</head>
</html>
child.tpl
{extends file="parent.tpl"}
{block name="title"}
You will see now - {$smarty.block.parent} - here
{/block}
The result would look like
<html>
<head>
<title>You will see now - Parent Title - here</title>
</head>
</html>
See also [Template
Inheritance](#advanced.features.template.inheritance),
[`$smarty.block.parent`](#language.variables.smarty.block.parent),
[`$smarty.block.child`](#language.variables.smarty.block.child), and
[`{extends}`](#language.function.extends)
@@ -0,0 +1,76 @@
{call} {#language.function.call}
======
`{call}` is used to call a template function defined by the
[`{function}`](#language.function.function) tag just like a plugin
function.
> **Note**
>
> Template functions are defined global. Since the Smarty compiler is a
> single-pass compiler, The [`{call}`](#language.function.call) tag must
> be used to call a template function defined externally from the given
> template. Otherwise you can directly use the function as
> `{funcname ...}` in the template.
- The `{call}` tag must have the `name` attribute which contains the
the name of the template function.
- Values for variables can be passed to the template function as
[attributes](#language.syntax.attributes).
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------------- ---------- --------- ------------------------------------------------------------------------------------------
name string Yes *n/a* The name of the template function
assign string No *n/a* The name of the variable that the output of called template function will be assigned to
\[var \...\] \[var type\] No *n/a* variable to pass local to template function
**Option Flags:**
Name Description
--------- --------------------------------------------
nocache Call the template function in nocache mode
{* define the function *}
{function name=menu level=0}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{call name=menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{* create an array to demonstrate *}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{* run the array through the function *}
{call name=menu data=$menu}
{call menu data=$menu} {* short-hand *}
Will generate the following output
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
See also [`{function}`](#language.function.function)
@@ -0,0 +1,82 @@
{capture} {#language.function.capture}
=========
`{capture}` is used to collect the output of the template between the
tags into a variable instead of displaying it. Any content between
`{capture name='foo'}` and `{/capture}` is collected into the variable
specified in the `name` attribute.
The captured content can be used in the template from the variable
[`$smarty.capture.foo`](#language.variables.smarty.capture) where "foo"
is the value passed in the `name` attribute. If you do not supply the
`name` attribute, then "default" will be used as the name ie
`$smarty.capture.default`.
`{capture}'s` can be nested.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ----------------------------------------------------------------------
name string Yes *n/a* The name of the captured block
assign string No *n/a* The variable name where to assign the captured output to
append string No *n/a* The name of an array variable where to append the captured output to
**Option Flags:**
Name Description
--------- -----------------------------------------
nocache Disables caching of this captured block
> **Note**
>
> Be careful when capturing [`{insert}`](#language.function.insert)
> output. If you have [`$caching`](#caching) enabled and you have
> [`{insert}`](#language.function.insert) commands that you expect to
> run within cached content, do not capture this content.
{* we don't want to print a div tag unless content is displayed *}
{capture name="banner"}
{capture "banner"} {* short-hand *}
{include file="get_banner.tpl"}
{/capture}
{if $smarty.capture.banner ne ""}
<div id="banner">{$smarty.capture.banner}</div>
{/if}
This example demonstrates the capture function.
{capture name=some_content assign=popText}
{capture some_content assign=popText} {* short-hand *}
The server is {$my_server_name|upper} at {$my_server_addr}<br>
Your ip is {$my_ip}.
{/capture}
<a href="#">{$popText}</a>
This example also demonstrates how multiple calls of capture can be used
to create an array with captured content.
{capture append="foo"}hello{/capture}I say just {capture append="foo"}world{/capture}
{foreach $foo as $text}{$text} {/foreach}
The above example will output:
I say just hello world
See also [`$smarty.capture`](#language.variables.smarty.capture),
[`{eval}`](#language.function.eval),
[`{fetch}`](#language.function.fetch), [`fetch()`](#api.fetch) and
[`{assign}`](#language.function.assign).
@@ -0,0 +1,91 @@
{config\_load} {#language.function.config.load}
==============
`{config_load}` is used for loading config
[`#variables#`](#language.config.variables) from a [configuration
file](#config.files) into the template.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
file string Yes *n/a* The name of the config file to include
section string No *n/a* The name of the section to load
scope string no *local* How the scope of the loaded variables are treated, which must be one of local, parent or global. local means variables are loaded into the local template context. parent means variables are loaded into both the local context and the parent template that called it. global means variables are available to all templates.
The `example.conf` file.
#this is config file comment
# global variables
pageTitle = "Main Menu"
bodyBgColor = #000000
tableBgColor = #000000
rowBgColor = #00ff00
#customer variables section
[Customer]
pageTitle = "Customer Info"
and the template
{config_load file="example.conf"}
{config_load "example.conf"} {* short-hand *}
<html>
<title>{#pageTitle#|default:"No title"}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
[Config Files](#config.files) may also contain sections. You can load
variables from within a section with the added attribute `section`. Note
that global config variables are always loaded along with section
variables, and same-named section variables overwrite the globals.
> **Note**
>
> Config file *sections* and the built-in template function called
> [`{section}`](#language.function.section) have nothing to do with each
> other, they just happen to share a common naming convention.
{config_load file='example.conf' section='Customer'}
{config_load 'example.conf' 'Customer'} {* short-hand *}
<html>
<title>{#pageTitle#}</title>
<body bgcolor="{#bodyBgColor#}">
<table border="{#tableBorderSize#}" bgcolor="{#tableBgColor#}">
<tr bgcolor="{#rowBgColor#}">
<td>First</td>
<td>Last</td>
<td>Address</td>
</tr>
</table>
</body>
</html>
See [`$config_overwrite`](#variable.config.overwrite) to create arrays
of config file variables.
See also the [config files](#config.files) page, [config
variables](#language.config.variables) page,
[`$config_dir`](#variable.config.dir),
[`getConfigVars()`](#api.get.config.vars) and
[`configLoad()`](#api.config.load).
@@ -0,0 +1,18 @@
{debug} {#language.function.debug}
=======
`{debug}` dumps the debug console to the page. This works regardless of
the [debug](#chapter.debugging.console) settings in the php script.
Since this gets executed at runtime, this is only able to show the
[assigned](#api.assign) variables; not the templates that are in use.
However, you can see all the currently available variables within the
scope of a template.
If caching is enabled and a page is loaded from cache `{debug}` does
show only the variables which assigned for the cached page.
In order to see also the variables which have been locally assigned
within the template it does make sense to place the `{debug}` tag at the
end of the template.
See also the [debugging console page](#chapter.debugging.console).
@@ -0,0 +1,37 @@
{extends} {#language.function.extends}
=========
`{extends}` tags are used in child templates in template inheritance for
extending parent templates. For details see section of [Template
Interitance](#advanced.features.template.inheritance).
- The `{extends}` tag must be on the first line of the template.
- If a child template extends a parent template with the `{extends}`
tag it may contain only `{block}` tags. Any other template content
is ignored.
- Use the syntax for [template resources](#resources) to extend files
outside of the [`$template_dir`](#variable.template.dir) directory.
> **Note**
>
> When extending a variable parent like `{extends file=$parent_file}`,
> make sure you include `$parent_file` in the
> [`$compile_id`](#variable.compile.id). Otherwise Smarty cannot
> distinguish between different `$parent_file`s.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------- ---------- --------- -------------------------------------------------
file string Yes *n/a* The name of the template file which is extended
{extends file='parent.tpl'}
{extends 'parent.tpl'} {* short-hand *}
See also [Template Interitance](#advanced.features.template.inheritance)
and [`{block}`](#language.function.block).
@@ -0,0 +1,97 @@
{for} {#language.function.for}
=====
The `{for}{forelse}` tag is used to create simple loops. The following
different formarts are supported:
- `{for $var=$start to $end}` simple loop with step size of 1.
- `{for $var=$start to $end step $step}` loop with individual step
size.
`{forelse}` is executed when the loop is not iterated.
**Attributes:**
Attribute Name Shorthand Type Required Default Description
---------------- ----------- --------- ---------- --------- --------------------------------
max n/a integer No *n/a* Limit the number of iterations
**Option Flags:**
Name Description
--------- --------------------------------------
nocache Disables caching of the `{for}` loop
<ul>
{for $foo=1 to 3}
<li>{$foo}</li>
{/for}
</ul>
The above example will output:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
$smarty->assign('to',10);
<ul>
{for $foo=3 to $to max=3}
<li>{$foo}</li>
{/for}
</ul>
The above example will output:
<ul>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
$smarty->assign('start',10);
$smarty->assign('to',5);
<ul>
{for $foo=$start to $to}
<li>{$foo}</li>
{forelse}
no iteration
{/for}
</ul>
The above example will output:
no iteration
See also [`{foreach}`](#language.function.foreach),
[`{section}`](#language.function.section) and
[`{while}`](#language.function.while)
@@ -0,0 +1,407 @@
{foreach},{foreachelse} {#language.function.foreach}
=======================
`{foreach}` is used for looping over arrays of data. `{foreach}` has a
simpler and cleaner syntax than the
[`{section}`](#language.function.section) loop, and can also loop over
associative arrays.
`{foreach $arrayvar as $itemvar}`
`{foreach $arrayvar as $keyvar=>$itemvar}`
> **Note**
>
> This foreach syntax does not accept any named attributes. This syntax
> is new to Smarty 3, however the Smarty 2.x syntax
> `{foreach from=$myarray key="mykey" item="myitem"}` is still
> supported.
- `{foreach}` loops can be nested.
- The `array` variable, usually an array of values, determines the
number of times `{foreach}` will loop. You can also pass an integer
for arbitrary loops.
- `{foreachelse}` is executed when there are no values in the `array`
variable.
- `{foreach}` properties are [`@index`](#foreach.property.index),
[`@iteration`](#foreach.property.iteration),
[`@first`](#foreach.property.first),
[`@last`](#foreach.property.last),
[`@show`](#foreach.property.show),
[`@total`](#foreach.property.total).
- `{foreach}` constructs are [`{break}`](#foreach.construct.break),
[`{continue}`](#foreach.construct.continue).
- Instead of specifying the `key` variable you can access the current
key of the loop item by `{$item@key}` (see examples below).
> **Note**
>
> The `$var@property` syntax is new to Smarty 3, however when using the
> Smarty 2 `{foreach from=$myarray key="mykey" item="myitem"}` style
> syntax, the `$smarty.foreach.name.property` syntax is still supported.
> **Note**
>
> Although you can retrieve the array key with the syntax
> `{foreach $myArray as $myKey => $myValue}`, the key is always
> available as `$myValue@key` within the foreach loop.
**Option Flags:**
Name Description
--------- ------------------------------------------
nocache Disables caching of the `{foreach}` loop
<?php
$arr = array('red', 'green', 'blue');
$smarty->assign('myColors', $arr);
?>
Template to output `$myColors` in an un-ordered list
<ul>
{foreach $myColors as $color}
<li>{$color}</li>
{/foreach}
</ul>
The above example will output:
<ul>
<li>red</li>
<li>green</li>
<li>blue</li>
</ul>
<?php
$people = array('fname' => 'John', 'lname' => 'Doe', 'email' => 'j.doe@example.com');
$smarty->assign('myPeople', $people);
?>
Template to output `$myArray` as key/value pairs.
<ul>
{foreach $myPeople as $value}
<li>{$value@key}: {$value}</li>
{/foreach}
</ul>
The above example will output:
<ul>
<li>fname: John</li>
<li>lname: Doe</li>
<li>email: j.doe@example.com</li>
</ul>
Assign an array to Smarty, the key contains the key for each looped
value.
<?php
$smarty->assign('contacts', array(
array('phone' => '555-555-1234',
'fax' => '555-555-5678',
'cell' => '555-555-0357'),
array('phone' => '800-555-4444',
'fax' => '800-555-3333',
'cell' => '800-555-2222')
));
?>
The template to output `$contact`.
{* key always available as a property *}
{foreach $contacts as $contact}
{foreach $contact as $value}
{$value@key}: {$value}
{/foreach}
{/foreach}
{* accessing key the PHP syntax alternate *}
{foreach $contacts as $contact}
{foreach $contact as $key => $value}
{$key}: {$value}
{/foreach}
{/foreach}
Either of the above examples will output:
phone: 555-555-1234
fax: 555-555-5678
cell: 555-555-0357
phone: 800-555-4444
fax: 800-555-3333
cell: 800-555-2222
A database (PDO) example of looping over search results. This example is
looping over a PHP iterator instead of an array().
<?php
include('Smarty.class.php');
$smarty = new Smarty;
$dsn = 'mysql:host=localhost;dbname=test';
$login = 'test';
$passwd = 'test';
// setting PDO to use buffered queries in mysql is
// important if you plan on using multiple result cursors
// in the template.
$db = new PDO($dsn, $login, $passwd, array(
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true));
$res = $db->prepare("select * from users");
$res->execute();
$res->setFetchMode(PDO::FETCH_LAZY);
// assign to smarty
$smarty->assign('res',$res);
$smarty->display('index.tpl');?>
?>
{foreach $res as $r}
{$r.id}
{$r.name}
{foreachelse}
.. no results ..
{/foreach}
The above is assuming the results contain the columns named `id` and
`name`.
What is the advantage of an iterator vs. looping over a plain old array?
With an array, all the results are accumulated into memory before being
looped. With an iterator, each result is loaded/released within the
loop. This saves processing time and memory, especially for very large
result sets.
\@index {#foreach.property.index}
-------
`index` contains the current array index, starting with zero.
{* output empty row on the 4th iteration (when index is 3) *}
<table>
{foreach $items as $i}
{if $i@index eq 3}
{* put empty table row *}
<tr><td>nbsp;</td></tr>
{/if}
<tr><td>{$i.label}</td></tr>
{/foreach}
</table>
\@iteration {#foreach.property.iteration}
-----------
`iteration` contains the current loop iteration and always starts at
one, unlike [`index`](#foreach.property.index). It is incremented by one
on each iteration.
The *\"is div by\"* operator can be used to detect a specific iteration.
Here we bold-face the name every 4th iteration.
{foreach $myNames as $name}
{if $name@iteration is div by 4}
<b>{$name}</b>
{/if}
{$name}
{/foreach}
The *\"is even by\"* and *\"is odd by\"* operators can be used to
alternate something every so many iterations. Choosing between even or
odd rotates which one starts. Here we switch the font color every 3rd
iteration.
{foreach $myNames as $name}
{if $name@iteration is even by 3}
<span style="color: #000">{$name}</span>
{else}
<span style="color: #eee">{$name}</span>
{/if}
{/foreach}
This will output something similar to this:
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #000">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
<span style="color: #eee">...</span>
...
\@first {#foreach.property.first}
-------
`first` is TRUE if the current `{foreach}` iteration is the initial one.
Here we display a table header row on the first iteration.
{* show table header at first iteration *}
<table>
{foreach $items as $i}
{if $i@first}
<tr>
<th>key</td>
<th>name</td>
</tr>
{/if}
<tr>
<td>{$i@key}</td>
<td>{$i.name}</td>
</tr>
{/foreach}
</table>
\@last {#foreach.property.last}
------
`last` is set to TRUE if the current `{foreach}` iteration is the final
one. Here we display a horizontal rule on the last iteration.
{* Add horizontal rule at end of list *}
{foreach $items as $item}
<a href="#{$item.id}">{$item.name}</a>{if $item@last}<hr>{else},{/if}
{foreachelse}
... no items to loop ...
{/foreach}
\@show {#foreach.property.show}
------
The show `show` property can be used after the execution of a
`{foreach}` loop to detect if data has been displayed or not. `show` is
a boolean value.
<ul>
{foreach $myArray as $name}
<li>{$name}</li>
{/foreach}
</ul>
{if $name@show} do something here if the array contained data {/if}
\@total {#foreach.property.total}
-------
`total` contains the number of iterations that this `{foreach}` will
loop. This can be used inside or after the `{foreach}`.
{* show number of rows at end *}
{foreach $items as $item}
{$item.name}<hr/>
{if $item@last}
<div id="total">{$item@total} items</div>
{/if}
{foreachelse}
... no items to loop ...
{/foreach}
See also [`{section}`](#language.function.section),
[`{for}`](#language.function.for) and
[`{while}`](#language.function.while)
{break} {#foreach.construct.break}
-------
`{break}` aborts the iteration of the array
{$data = [1,2,3,4,5]}
{foreach $data as $value}
{if $value == 3}
{* abort iterating the array *}
{break}
{/if}
{$value}
{/foreach}
{*
prints: 1 2
*}
{continue} {#foreach.construct.continue}
----------
`{continue}` leaves the current iteration and begins with the next
iteration.
{$data = [1,2,3,4,5]}
{foreach $data as $value}
{if $value == 3}
{* skip this iteration *}
{continue}
{/if}
{$value}
{/foreach}
{*
prints: 1 2 4 5
*}
@@ -0,0 +1,88 @@
{function} {#language.function.function}
==========
`{function}` is used to create functions within a template and call them
just like a plugin function. Instead of writing a plugin that generates
presentational content, keeping it in the template is often a more
manageable choice. It also simplifies data traversal, such as deeply
nested menus.
> **Note**
>
> Template functions are defined global. Since the Smarty compiler is a
> single-pass compiler, The [`{call}`](#language.function.call) tag must
> be used to call a template function defined externally from the given
> template. Otherwise you can directly use the function as
> `{funcname ...}` in the template.
- The `{function}` tag must have the `name` attribute which contains
the the name of the template function. A tag with this name can be
used to call the template function.
- Default values for variables can be passed to the template function
as [attributes](#language.syntax.attributes). Like in PHP function
declarations you can only use scalar values as default. The default
values can be overwritten when the template function is being
called.
- You can use all variables from the calling template inside the
template function. Changes to variables or new created variables
inside the template function have local scope and are not visible
inside the calling template after the template function is executed.
**Attributes:**
Attribute Name Type Required Default Description
---------------- -------------- ---------- --------- ---------------------------------------------------------------
name string Yes *n/a* The name of the template function
\[var \...\] \[var type\] No *n/a* default variable value to pass local to the template function
> **Note**
>
> You can pass any number of parameter to the template function when it
> is called. The parameter variables must not be declared in the
> `{funcname ...}` tag unless you what to use default values. Default
> values must be scalar and can not be variable. Variables must be
> passed when the template is called.
{* define the function *}
{function name=menu level=0}
{function menu level=0} {* short-hand *}
<ul class="level{$level}">
{foreach $data as $entry}
{if is_array($entry)}
<li>{$entry@key}</li>
{menu data=$entry level=$level+1}
{else}
<li>{$entry}</li>
{/if}
{/foreach}
</ul>
{/function}
{* create an array to demonstrate *}
{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
['item3-3-1','item3-3-2']],'item4']}
{* run the array through the function *}
{menu data=$menu}
Will generate the following output
* item1
* item2
* item3
o item3-1
o item3-2
o item3-3
+ item3-3-1
+ item3-3-2
* item4
See also [`{call}`](#language.function.call)
@@ -0,0 +1,121 @@
{if},{elseif},{else} {#language.function.if}
====================
`{if}` statements in Smarty have much the same flexibility as PHP
[if](&url.php-manual;if) statements, with a few added features for the
template engine. Every `{if}` must be paired with a matching `{/if}`.
`{else}` and `{elseif}` are also permitted. All PHP conditionals and
functions are recognized, such as *\|\|*, *or*, *&&*, *and*,
*is\_array()*, etc.
If securty is enabled, only PHP functions from `$php_functions` property
of the securty policy are allowed. See the
[Security](#advanced.features.security) section for details.
The following is a list of recognized qualifiers, which must be
separated from surrounding elements by spaces. Note that items listed in
\[brackets\] are optional. PHP equivalents are shown where applicable.
Qualifier Alternates Syntax Example Meaning PHP Equivalent
-------------------- ------------ ------------------------ -------------------------------- ----------------------
== eq \$a eq \$b equals ==
!= ne, neq \$a neq \$b not equals !=
\> gt \$a gt \$b greater than \>
\< lt \$a lt \$b less than \<
\>= gte, ge \$a ge \$b greater than or equal \>=
\<= lte, le \$a le \$b less than or equal \<=
=== \$a === 0 check for identity ===
! not not \$a negation (unary) !
\% mod \$a mod \$b modulous \%
is \[not\] div by \$a is not div by 4 divisible by \$a % \$b == 0
is \[not\] even \$a is not even \[not\] an even number (unary) \$a % 2 == 0
is \[not\] even by \$a is not even by \$b grouping level \[not\] even (\$a / \$b) % 2 == 0
is \[not\] odd \$a is not odd \[not\] an odd number (unary) \$a % 2 != 0
is \[not\] odd by \$a is not odd by \$b \[not\] an odd grouping (\$a / \$b) % 2 != 0
{if $name eq 'Fred'}
Welcome Sir.
{elseif $name eq 'Wilma'}
Welcome Ma'am.
{else}
Welcome, whatever you are.
{/if}
{* an example with "or" logic *}
{if $name eq 'Fred' or $name eq 'Wilma'}
...
{/if}
{* same as above *}
{if $name == 'Fred' || $name == 'Wilma'}
...
{/if}
{* parenthesis are allowed *}
{if ( $amount < 0 or $amount > 1000 ) and $volume >= #minVolAmt#}
...
{/if}
{* you can also embed php function calls *}
{if count($var) gt 0}
...
{/if}
{* check for array. *}
{if is_array($foo) }
.....
{/if}
{* check for not null. *}
{if isset($foo) }
.....
{/if}
{* test if values are even or odd *}
{if $var is even}
...
{/if}
{if $var is odd}
...
{/if}
{if $var is not odd}
...
{/if}
{* test if var is divisible by 4 *}
{if $var is div by 4}
...
{/if}
{*
test if var is even, grouped by two. i.e.,
0=even, 1=even, 2=odd, 3=odd, 4=even, 5=even, etc.
*}
{if $var is even by 2}
...
{/if}
{* 0=even, 1=even, 2=even, 3=odd, 4=odd, 5=odd, etc. *}
{if $var is even by 3}
...
{/if}
{if isset($name) && $name == 'Blog'}
{* do something *}
{elseif $name == $foo}
{* do something *}
{/if}
{if is_array($foo) && count($foo) > 0}
{* do a foreach loop *}
{/if}
@@ -0,0 +1,74 @@
{include\_php} {#language.function.include.php}
==============
> **Note**
>
> `{include_php}` is deprecated from Smarty, use registered plugins to
> properly insulate presentation from the application code. As of Smarty
> 3.1 the `{include_php}` tags are only available from [SmartyBC](#bc).
Attribute Name Type Required Default Description
---------------- --------- ---------- --------- ----------------------------------------------------------------------------------
file string Yes *n/a* The name of the php file to include as absolute path
once boolean No *TRUE* whether or not to include the php file more than once if included multiple times
assign string No *n/a* The name of the variable that the output of include\_php will be assigned to
**Option Flags:**
Name Description
--------- ----------------------------------------
nocache Disables caching of inluded PHP script
`{include_php}` tags are used to include a php script in your template.
The path of the attribute `file` can be either absolute, or relative to
[`$trusted_dir`](#variable.trusted.dir). If security is enabled, then
the script must be located in the `$trusted_dir` path of the securty
policy. See the [Security](#advanced.features.security) section for
details.
By default, php files are only included once even if called multiple
times in the template. You can specify that it should be included every
time with the `once` attribute. Setting once to FALSE will include the
php script each time it is included in the template.
You can optionally pass the `assign` attribute, which will specify a
template variable name that the output of `{include_php}` will be
assigned to instead of displayed.
The smarty object is available as `$_smarty_tpl->smarty` within the PHP
script that you include.
The `load_nav.php` file:
<?php
// load in variables from a mysql db and assign them to the template
require_once('database.class.php');
$db = new Db();
$db->query('select url, name from navigation order by name');
$this->assign('navigation', $db->getRows());
?>
where the template is:
{* absolute path, or relative to $trusted_dir *}
{include_php file='/path/to/load_nav.php'}
{include_php '/path/to/load_nav.php'} {* short-hand *}
{foreach item='nav' from=$navigation}
<a href="{$nav.url}">{$nav.name}</a><br />
{/foreach}
See also [`{include}`](#language.function.include),
[`$trusted_dir`](#variable.trusted.dir),
[`{php}`](#language.function.php),
[`{capture}`](#language.function.capture), [template
resources](#resources) and [componentized
templates](#tips.componentized.templates)
@@ -0,0 +1,194 @@
{include} {#language.function.include}
=========
`{include}` tags are used for including other templates in the current
template. Any variables available in the current template are also
available within the included template.
- The `{include}` tag must have the `file` attribute which contains
the template resource path.
- Setting the optional `assign` attribute specifies the template
variable that the output of `{include}` is assigned to, instead of
being displayed. Similar to [`{assign}`](#language.function.assign).
- Variables can be passed to included templates as
[attributes](#language.syntax.attributes). Any variables explicitly
passed to an included template are only available within the scope
of the included file. Attribute variables override current template
variables, in the case when they are named the same.
- You can use all variables from the including template inside the
included template. But changes to variables or new created variables
inside the included template have local scope and are not visible
inside the including template after the `{include}` statement. This
default behaviour can be changed for all variables assigned in the
included template by using the scope attribute at the `{include}`
statement or for individual variables by using the scope attribute
at the [`{assign}`](#language.function.assign) statement. The later
is useful to return values from the included template to the
including template.
- Use the syntax for [template resources](#resources) to `{include}`
files outside of the [`$template_dir`](#variable.template.dir)
directory.
**Attributes:**
Attribute Name Type Required Default Description
----------------- ---------------- ---------- --------- --------------------------------------------------------------------------------------------------
file string Yes *n/a* The name of the template file to include
assign string No *n/a* The name of the variable that the output of include will be assigned to
cache\_lifetime integer No *n/a* Enable caching of this subtemplate with an individual cache lifetime
compile\_id string/integer No *n/a* Compile this subtemplate with an individual compile\_id
cache\_id string/integer No *n/a* Enable caching of this subtemplate with an individual cache\_id
scope string No *n/a* Define the scope of all in the subtemplate assigned variables: \'parent\',\'root\' or \'global\'
\[var \...\] \[var type\] No *n/a* variable to pass local to template
**Option Flags:**
Name Description
--------- -------------------------------------------------------------------------------------
nocache Disables caching of this subtemplate
caching Enable caching of this subtemplate
inline If set merge the compile code of the subtemplate into the compiled calling template
<html>
<head>
<title>{$title}</title>
</head>
<body>
{include file='page_header.tpl'}
{* body of template goes here, the $tpl_name variable
is replaced with a value eg 'contact.tpl'
*}
{include file="$tpl_name.tpl"}
{* using shortform file attribute *}
{include 'page_footer.tpl'}
</body>
</html>
{include 'links.tpl' title='Newest links' links=$link_array}
{* body of template goes here *}
{include 'footer.tpl' foo='bar'}
The template above includes the example `links.tpl` below
<div id="box">
<h3>{$title}{/h3>
<ul>
{foreach from=$links item=l}
.. do stuff ...
</foreach}
</ul>
</div>
Variables assigned in the included template will be seen in the
including template.
{include 'sub_template.tpl' scope=parent}
...
{* display variables assigned in sub_template *}
{$foo}<br>
{$bar}<br>
...
The template above includes the example `sub_template.tpl` below
...
{assign var=foo value='something'}
{assign var=bar value='value'}
...
The included template will not be cached.
{include 'sub_template.tpl' nocache}
...
In this example included template will be cached with an individual
cache lifetime of 500 seconds.
{include 'sub_template.tpl' cache_lifetime=500}
...
In this example included template will be cached independent of the
global cahing setting.
{include 'sub_template.tpl' caching}
...
This example assigns the contents of `nav.tpl` to the `$navbar`
variable, which is then output at both the top and bottom of the page.
<body>
{include 'nav.tpl' assign=navbar}
{include 'header.tpl' title='Smarty is cool'}
{$navbar}
{* body of template goes here *}
{$navbar}
{include 'footer.tpl'}
</body>
This example includes another template relative to the directory of the
current template.
{include 'template-in-a-template_dir-directory.tpl'}
{include './template-in-same-directory.tpl'}
{include '../template-in-parent-directory.tpl'}
{* absolute filepath *}
{include file='/usr/local/include/templates/header.tpl'}
{* absolute filepath (same thing) *}
{include file='file:/usr/local/include/templates/header.tpl'}
{* windows absolute filepath (MUST use "file:" prefix) *}
{include file='file:C:/www/pub/templates/header.tpl'}
{* include from template resource named "db" *}
{include file='db:header.tpl'}
{* include a $variable template - eg $module = 'contacts' *}
{include file="$module.tpl"}
{* wont work as its single quotes ie no variable substitution *}
{include file='$module.tpl'}
{* include a multi $variable template - eg amber/links.view.tpl *}
{include file="$style_dir/$module.$view.tpl"}
See also [`{include_php}`](#language.function.include.php),
[`{insert}`](#language.function.insert),
[`{php}`](#language.function.php), [template resources](#resources) and
[componentized templates](#tips.componentized.templates).
@@ -0,0 +1,86 @@
{insert} {#language.function.insert}
========
> **Note**
>
> `{insert}` tags are deprecated from Smarty, and should not be used.
> Put your PHP logic in PHP scripts or plugin functions instead.
> **Note**
>
> As of Smarty 3.1 the `{insert}` tags are only available from
> [SmartyBC](#bc).
`{insert}` tags work much like [`{include}`](#language.function.include)
tags, except that `{insert}` tags are NOT cached when template
[caching](#caching) is enabled. They will be executed on every
invocation of the template.
Attribute Name Type Required Default Description
---------------- -------------- ---------- --------- ----------------------------------------------------------------------------------
name string Yes *n/a* The name of the insert function (insert\_`name`) or insert plugin
assign string No *n/a* The name of the template variable the output will be assigned to
script string No *n/a* The name of the php script that is included before the insert function is called
\[var \...\] \[var type\] No *n/a* variable to pass to insert function
Let\'s say you have a template with a banner slot at the top of the
page. The banner can contain any mixture of HTML, images, flash, etc. so
we can\'t just use a static link here, and we don\'t want this contents
cached with the page. In comes the {insert} tag: the template knows
\#banner\_location\_id\# and \#site\_id\# values (gathered from a
[config file](#config.files)), and needs to call a function to get the
banner contents.
{* example of fetching a banner *}
{insert name="getBanner" lid=#banner_location_id# sid=#site_id#}
{insert "getBanner" lid=#banner_location_id# sid=#site_id#} {* short-hand *}
In this example, we are using the name "getBanner" and passing the
parameters \#banner\_location\_id\# and \#site\_id\#. Smarty will look
for a function named insert\_getBanner() in your PHP application,
passing the values of \#banner\_location\_id\# and \#site\_id\# as the
first argument in an associative array. All {insert} function names in
your application must be prepended with \"insert\_\" to remedy possible
function name-space conflicts. Your insert\_getBanner() function should
do something with the passed values and return the results. These
results are then displayed in the template in place of the {insert} tag.
In this example, Smarty would call this function:
insert\_getBanner(array(\"lid\" =\> \"12345\",\"sid\" =\> \"67890\"));
and display the returned results in place of the {insert} tag.
- If you supply the `assign` attribute, the output of the `{insert}`
tag will be assigned to this template variable instead of being
output to the template.
> **Note**
>
> Assigning the output to a template variable isn\'t too useful with
> [caching](#variable.caching) enabled.
- If you supply the `script` attribute, this php script will be
included (only once) before the `{insert}` function is executed.
This is the case where the insert function may not exist yet, and a
php script must be included first to make it work.
The path can be either absolute, or relative to
[`$trusted_dir`](#variable.trusted.dir). If security is enabled,
then the script must be located in the `$trusted_dir` path of the
securty policy. See the [Security](#advanced.features.security)
section for details.
The Smarty object is passed as the second argument. This way you can
reference and modify information in the Smarty object from within the
`{insert}` function.
If no PHP script can be found Smarty is looking for a corresponding
insert plugin.
> **Note**
>
> It is possible to have portions of the template not cached. If you
> have [caching](#caching) turned on, `{insert}` tags will not be
> cached. They will run dynamically every time the page is created, even
> within cached pages. This works good for things like banners, polls,
> live weather, search results, user feedback areas, etc.
See also [`{include}`](#language.function.include)
@@ -0,0 +1,55 @@
{ldelim},{rdelim} {#language.function.ldelim}
=================
`{ldelim}` and `{rdelim}` are used for [escaping](#language.escaping)
template delimiters, by default **{** and **}**. You can also use
[`{literal}{/literal}`](#language.function.literal) to escape blocks of
text eg Javascript or CSS. See also the complementary
[`{$smarty.ldelim}`](#language.variables.smarty.ldelim).
{* this will print literal delimiters out of the template *}
{ldelim}funcname{rdelim} is how functions look in Smarty!
The above example will output:
{funcname} is how functions look in Smarty!
Another example with some Javascript
<script language="JavaScript">
function foo() {ldelim}
... code ...
{rdelim}
</script>
will output
<script language="JavaScript">
function foo() {
.... code ...
}
</script>
<script language="JavaScript" type="text/javascript">
function myJsFunction(){ldelim}
alert("The server name\n{$smarty.server.SERVER_NAME}\n{$smarty.server.SERVER_ADDR}");
{rdelim}
</script>
<a href="javascript:myJsFunction()">Click here for Server Info</a>
See also [`{literal}`](#language.function.literal) and [escaping Smarty
parsing](#language.escaping).
@@ -0,0 +1,36 @@
{literal} {#language.function.literal}
=========
`{literal}` tags allow a block of data to be taken literally. This is
typically used around Javascript or stylesheet blocks where {curly
braces} would interfere with the template
[delimiter](#variable.left.delimiter) syntax. Anything within
`{literal}{/literal}` tags is not interpreted, but displayed as-is. If
you need template tags embedded in a `{literal}` block, consider using
[`{ldelim}{rdelim}`](#language.function.ldelim) to escape the individual
delimiters instead.
> **Note**
>
> `{literal}{/literal}` tags are normally not necessary, as Smarty
> ignores delimiters that are surrounded by whitespace. Be sure your
> javascript and CSS curly braces are surrounded by whitespace. This is
> new behavior to Smarty 3.
<script>
// the following braces are ignored by Smarty
// since they are surrounded by whitespace
function myFoo {
alert('Foo!');
}
// this one will need literal escapement
{literal}
function myBar {alert('Bar!');}
{/literal}
</script>
See also [`{ldelim} {rdelim}`](#language.function.ldelim) and the
[escaping Smarty parsing](#language.escaping) page.
@@ -0,0 +1,23 @@
{nocache} {#language.function.nocache}
=========
`{nocache}` is used to disable caching of a template section. Every
`{nocache}` must be paired with a matching `{/nocache}`.
> **Note**
>
> Be sure any variables used within a non-cached section are also
> assigned from PHP when the page is loaded from the cache.
Today's date is
{nocache}
{$smarty.now|date_format}
{/nocache}
The above code will output the current date on a cached page.
See also the [caching section](#caching).
@@ -0,0 +1,644 @@
{section},{sectionelse} {#language.function.section}
=======================
A `{section}` is for looping over **sequentially indexed arrays of
data**, unlike [`{foreach}`](#language.function.foreach) which is used
to loop over a **single associative array**. Every `{section}` tag must
be paired with a closing `{/section}` tag.
> **Note**
>
> The [`{foreach}`](#language.function.foreach) loop can do everything a
> {section} loop can do, and has a simpler and easier syntax. It is
> usually preferred over the {section} loop.
> **Note**
>
> {section} loops cannot loop over associative arrays, they must be
> numerically indexed, and sequential (0,1,2,\...). For associative
> arrays, use the [`{foreach}`](#language.function.foreach) loop.
Attribute Name Type Required Default Description
---------------- --------- ---------- --------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name string Yes *n/a* The name of the section
loop mixed Yes *n/a* Value to determine the number of loop iterations
start integer No *0* The index position that the section will begin looping. If the value is negative, the start position is calculated from the end of the array. For example, if there are seven values in the loop array and start is -2, the start index is 5. Invalid values (values outside of the length of the loop array) are automatically truncated to the closest valid value.
step integer No *1* The step value that will be used to traverse the loop array. For example, step=2 will loop on index 0,2,4, etc. If step is negative, it will step through the array backwards.
max integer No *n/a* Sets the maximum number of times the section will loop.
show boolean No *TRUE* Determines whether or not to show this section
**Option Flags:**
Name Description
--------- ------------------------------------------
nocache Disables caching of the `{section}` loop
- Required attributes are `name` and `loop`.
- The `name` of the `{section}` can be anything you like, made up of
letters, numbers and underscores, like [PHP
variables](&url.php-manual;language.variables).
- {section}\'s can be nested, and the nested `{section}` names must be
unique from each other.
- The `loop` attribute, usually an array of values, determines the
number of times the `{section}` will loop. You can also pass an
integer as the loop value.
- When printing a variable within a `{section}`, the `{section}`
`name` must be given next to variable name within \[brackets\].
- `{sectionelse}` is executed when there are no values in the loop
variable.
- A `{section}` also has its own variables that handle `{section}`
properties. These properties are accessible as:
[`{$smarty.section.name.property}`](#language.variables.smarty.loops)
where "name" is the attribute `name`.
- `{section}` properties are [`index`](#section.property.index),
[`index_prev`](#section.property.index.prev),
[`index_next`](#section.property.index.next),
[`iteration`](#section.property.iteration),
[`first`](#section.property.first),
[`last`](#section.property.last),
[`rownum`](#section.property.rownum),
[`loop`](#section.property.loop), [`show`](#section.property.show),
[`total`](#section.property.total).
[`assign()`](#api.assign) an array to Smarty
<?php
$data = array(1000,1001,1002);
$smarty->assign('custid',$data);
?>
The template that outputs the array
{* this example will print out all the values of the $custid array *}
{section name=customer loop=$custid}
{section customer $custid} {* short-hand *}
id: {$custid[customer]}<br />
{/section}
<hr />
{* print out all the values of the $custid array reversed *}
{section name=foo loop=$custid step=-1}
{section foo $custid step=-1} {* short-hand *}
{$custid[foo]}<br />
{/section}
The above example will output:
id: 1000<br />
id: 1001<br />
id: 1002<br />
<hr />
id: 1002<br />
id: 1001<br />
id: 1000<br />
{section name=foo start=10 loop=20 step=2}
{$smarty.section.foo.index}
{/section}
<hr />
{section name=bar loop=21 max=6 step=-2}
{$smarty.section.bar.index}
{/section}
The above example will output:
10 12 14 16 18
<hr />
20 18 16 14 12 10
The `name` of the `{section}` can be anything you like, see [PHP
variables](&url.php-manual;language.variables). It is used to reference
the data within the `{section}`.
{section name=anything loop=$myArray}
{$myArray[anything].foo}
{$name[anything]}
{$address[anything].bar}
{/section}
This is an example of printing an associative array of data with a
`{section}`. Following is the php script to assign the `$contacts` array
to Smarty.
<?php
$data = array(
array('name' => 'John Smith', 'home' => '555-555-5555',
'cell' => '666-555-5555', 'email' => 'john@myexample.com'),
array('name' => 'Jack Jones', 'home' => '777-555-5555',
'cell' => '888-555-5555', 'email' => 'jack@myexample.com'),
array('name' => 'Jane Munson', 'home' => '000-555-5555',
'cell' => '123456', 'email' => 'jane@myexample.com')
);
$smarty->assign('contacts',$data);
?>
The template to output `$contacts`
{section name=customer loop=$contacts}
<p>
name: {$contacts[customer].name}<br />
home: {$contacts[customer].home}<br />
cell: {$contacts[customer].cell}<br />
e-mail: {$contacts[customer].email}
</p>
{/section}
The above example will output:
<p>
name: John Smith<br />
home: 555-555-5555<br />
cell: 666-555-5555<br />
e-mail: john@myexample.com
</p>
<p>
name: Jack Jones<br />
home phone: 777-555-5555<br />
cell phone: 888-555-5555<br />
e-mail: jack@myexample.com
</p>
<p>
name: Jane Munson<br />
home phone: 000-555-5555<br />
cell phone: 123456<br />
e-mail: jane@myexample.com
</p>
This example assumes that `$custid`, `$name` and `$address` are all
arrays containing the same number of values. First the php script that
assign\'s the arrays to Smarty.
<?php
$id = array(1001,1002,1003);
$smarty->assign('custid',$id);
$fullnames = array('John Smith','Jack Jones','Jane Munson');
$smarty->assign('name',$fullnames);
$addr = array('253 Abbey road', '417 Mulberry ln', '5605 apple st');
$smarty->assign('address',$addr);
?>
The `loop` variable only determines the number of times to loop. You can
access ANY variable from the template within the `{section}`. This is
useful for looping multiple arrays. You can pass an array which will
determine the loop count by the array size, or you can pass an integer
to specify the number of loops.
{section name=customer loop=$custid}
<p>
id: {$custid[customer]}<br />
name: {$name[customer]}<br />
address: {$address[customer]}
</p>
{/section}
The above example will output:
<p>
id: 1000<br />
name: John Smith<br />
address: 253 Abbey road
</p>
<p>
id: 1001<br />
name: Jack Jones<br />
address: 417 Mulberry ln
</p>
<p>
id: 1002<br />
name: Jane Munson<br />
address: 5605 apple st
</p>
{section}\'s can be nested as deep as you like. With nested
{section}\'s, you can access complex data structures, such as
multi-dimensional arrays. This is an example `.php` script thats
assign\'s the arrays.
<?php
$id = array(1001,1002,1003);
$smarty->assign('custid',$id);
$fullnames = array('John Smith','Jack Jones','Jane Munson');
$smarty->assign('name',$fullnames);
$addr = array('253 N 45th', '417 Mulberry ln', '5605 apple st');
$smarty->assign('address',$addr);
$types = array(
array( 'home phone', 'cell phone', 'e-mail'),
array( 'home phone', 'web'),
array( 'cell phone')
);
$smarty->assign('contact_type', $types);
$info = array(
array('555-555-5555', '666-555-5555', 'john@myexample.com'),
array( '123-456-4', 'www.example.com'),
array( '0457878')
);
$smarty->assign('contact_info', $info);
?>
In this template, *\$contact\_type\[customer\]* is an array of contact
types for the current customer.
{section name=customer loop=$custid}
<hr>
id: {$custid[customer]}<br />
name: {$name[customer]}<br />
address: {$address[customer]}<br />
{section name=contact loop=$contact_type[customer]}
{$contact_type[customer][contact]}: {$contact_info[customer][contact]}<br />
{/section}
{/section}
The above example will output:
<hr>
id: 1000<br />
name: John Smith<br />
address: 253 N 45th<br />
home phone: 555-555-5555<br />
cell phone: 666-555-5555<br />
e-mail: john@myexample.com<br />
<hr>
id: 1001<br />
name: Jack Jones<br />
address: 417 Mulberry ln<br />
home phone: 123-456-4<br />
web: www.example.com<br />
<hr>
id: 1002<br />
name: Jane Munson<br />
address: 5605 apple st<br />
cell phone: 0457878<br />
Results of a database search (eg ADODB or PEAR) are assigned to Smarty
<?php
$sql = 'select id, name, home, cell, email from contacts '
."where name like '$foo%' ";
$smarty->assign('contacts', $db->getAll($sql));
?>
The template to output the database result in a HTML table
<table>
<tr><th>&nbsp;</th><th>Name></th><th>Home</th><th>Cell</th><th>Email</th></tr>
{section name=co loop=$contacts}
<tr>
<td><a href="view.php?id={$contacts[co].id}">view<a></td>
<td>{$contacts[co].name}</td>
<td>{$contacts[co].home}</td>
<td>{$contacts[co].cell}</td>
<td>{$contacts[co].email}</td>
<tr>
{sectionelse}
<tr><td colspan="5">No items found</td></tr>
{/section}
</table>
.index {#section.property.index}
------
`index` contains the current array index, starting with zero or the
`start` attribute if given. It increments by one or by the `step`
attribute if given.
> **Note**
>
> If the `step` and `start` properties are not modified, then this works
> the same as the [`iteration`](#section.property.iteration) property,
> except it starts at zero instead of one.
> **Note**
>
> `$custid[customer.index]` and `$custid[customer]` are identical.
{section name=customer loop=$custid}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
The above example will output:
0 id: 1000<br />
1 id: 1001<br />
2 id: 1002<br />
.index\_prev {#section.property.index.prev}
------------
`index_prev` is the previous loop index. On the first loop, this is set
to -1.
.index\_next {#section.property.index.next}
------------
`index_next` is the next loop index. On the last loop, this is still one
more than the current index, respecting the setting of the `step`
attribute, if given.
<?php
$data = array(1001,1002,1003,1004,1005);
$smarty->assign('rows',$data);
?>
Template to output the above array in a table
{* $rows[row.index] and $rows[row] are identical in meaning *}
<table>
<tr>
<th>index</th><th>id</th>
<th>index_prev</th><th>prev_id</th>
<th>index_next</th><th>next_id</th>
</tr>
{section name=row loop=$rows}
<tr>
<td>{$smarty.section.row.index}</td><td>{$rows[row]}</td>
<td>{$smarty.section.row.index_prev}</td><td>{$rows[row.index_prev]}</td>
<td>{$smarty.section.row.index_next}</td><td>{$rows[row.index_next]}</td>
</tr>
{/section}
</table>
The above example will output a table containing the following:
index id index_prev prev_id index_next next_id
0 1001 -1 1 1002
1 1002 0 1001 2 1003
2 1003 1 1002 3 1004
3 1004 2 1003 4 1005
4 1005 3 1004 5
.iteration {#section.property.iteration}
----------
`iteration` contains the current loop iteration and starts at one.
> **Note**
>
> This is not affected by the `{section}` properties `start`, `step` and
> `max`, unlike the [`index`](#section.property.index) property.
> `iteration` also starts with one instead of zero unlike `index`.
> [`rownum`](#section.property.rownum) is an alias to `iteration`, they
> are identical.
<?php
// array of 3000 to 3015
$id = range(3000,3015);
$smarty->assign('arr',$id);
?>
Template to output every other element of the `$arr` array as `step=2`
{section name=cu loop=$arr start=5 step=2}
iteration={$smarty.section.cu.iteration}
index={$smarty.section.cu.index}
id={$custid[cu]}<br />
{/section}
The above example will output:
iteration=1 index=5 id=3005<br />
iteration=2 index=7 id=3007<br />
iteration=3 index=9 id=3009<br />
iteration=4 index=11 id=3011<br />
iteration=5 index=13 id=3013<br />
iteration=6 index=15 id=3015<br />
Another example that uses the `iteration` property to output a table
header block every five rows.
<table>
{section name=co loop=$contacts}
{if $smarty.section.co.iteration is div by 5}
<tr><th>&nbsp;</th><th>Name></th><th>Home</th><th>Cell</th><th>Email</th></tr>
{/if}
<tr>
<td><a href="view.php?id={$contacts[co].id}">view<a></td>
<td>{$contacts[co].name}</td>
<td>{$contacts[co].home}</td>
<td>{$contacts[co].cell}</td>
<td>{$contacts[co].email}</td>
<tr>
{/section}
</table>
An that uses the `iteration` property to alternate a text color every
third row.
<table>
{section name=co loop=$contacts}
{if $smarty.section.co.iteration is even by 3}
<span style="color: #ffffff">{$contacts[co].name}</span>
{else}
<span style="color: #dddddd">{$contacts[co].name}</span>
{/if}
{/section}
</table>
> **Note**
>
> The *\"is div by\"* syntax is a simpler alternative to the PHP mod
> operator syntax. The mod operator is allowed:
> `{if $smarty.section.co.iteration % 5 == 1}` will work just the same.
> **Note**
>
> You can also use *\"is odd by\"* to reverse the alternating.
.first {#section.property.first}
------
`first` is set to TRUE if the current `{section}` iteration is the
initial one.
.last {#section.property.last}
-----
`last` is set to TRUE if the current section iteration is the final one.
This example loops the `$customers` array, outputs a header block on the
first iteration and on the last outputs the footer block. Also uses the
[`total`](#section.property.total) property.
{section name=customer loop=$customers}
{if $smarty.section.customer.first}
<table>
<tr><th>id</th><th>customer</th></tr>
{/if}
<tr>
<td>{$customers[customer].id}}</td>
<td>{$customers[customer].name}</td>
</tr>
{if $smarty.section.customer.last}
<tr><td></td><td>{$smarty.section.customer.total} customers</td></tr>
</table>
{/if}
{/section}
.rownum {#section.property.rownum}
-------
`rownum` contains the current loop iteration, starting with one. It is
an alias to [`iteration`](#section.property.iteration), they work
identically.
.loop {#section.property.loop}
-----
`loop` contains the last index number that this {section} looped. This
can be used inside or after the `{section}`.
{section name=customer loop=$custid}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
There are {$smarty.section.customer.loop} customers shown above.
The above example will output:
0 id: 1000<br />
1 id: 1001<br />
2 id: 1002<br />
There are 3 customers shown above.
.show {#section.property.show}
-----
`show` is used as a parameter to section and is a boolean value. If
FALSE, the section will not be displayed. If there is a `{sectionelse}`
present, that will be alternately displayed.
Boolean `$show_customer_info` has been passed from the PHP application,
to regulate whether or not this section shows.
{section name=customer loop=$customers show=$show_customer_info}
{$smarty.section.customer.rownum} id: {$customers[customer]}<br />
{/section}
{if $smarty.section.customer.show}
the section was shown.
{else}
the section was not shown.
{/if}
The above example will output:
1 id: 1000<br />
2 id: 1001<br />
3 id: 1002<br />
the section was shown.
.total {#section.property.total}
------
`total` contains the number of iterations that this `{section}` will
loop. This can be used inside or after a `{section}`.
{section name=customer loop=$custid step=2}
{$smarty.section.customer.index} id: {$custid[customer]}<br />
{/section}
There are {$smarty.section.customer.total} customers shown above.
See also [`{foreach}`](#language.function.foreach),
[`{for}`](#language.function.for), [`{while}`](#language.function.while)
and [`$smarty.section`](#language.variables.smarty.loops).
@@ -0,0 +1,42 @@
{setfilter} {#language.function.setfilter}
===========
The `{setfilter}...{/setfilter}` block tag allows the definition of
template instance\'s variable filters.
SYNTAX: {setfilter filter1\|filter2\|filter3\....}\...{/setfilter}
The filter can be:
- A variable filter plugin specified by it\'s name.
- A modidier specified by it\'s name and optional additional
parameter.
`{setfilter}...{/setfilter}` blocks can be nested. The filter definition
of inner blocks does replace the definition of the outer block.
Template instance filters run in addition to other modifiers and
filters. They run in the following order: modifier, default\_modifier,
\$escape\_html, registered variable filters, autoloaded variable
filters, template instance\'s variable filters. Everything after
default\_modifier can be disabled with the `nofilter` flag.
<script>
{setfilter filter1}
{$foo} {* filter1 runs on output of $foo *}
{setfilter filter2|mod:true}
{$bar} {* filter2 and modifier mod runs on output of $bar *}
{/setfilter}
{$buh} {* filter1 runs on output of $buh *}
{/setfilter}
{$blar} {* no template instance filter runs on output of $blar}
</script>
> **Note**
>
> The setting of template instance filters does not effect the output of
> included subtemplates.
@@ -0,0 +1,84 @@
{\$var=\...} {#language.function.shortform.assign}
============
This is a short-hand version of the {assign} function. You can assign
values directly to the template, or assign values to array elements too.
> **Note**
>
> Assignment of variables in-template is essentially placing application
> logic into the presentation that may be better handled in PHP. Use at
> your own discretion.
The following attributes can be added to the tag:
**Attributes:**
Attribute Name Shorthand Type Required Default Description
---------------- ----------- -------- ---------- --------- -----------------------------------------------------------------------
scope n/a string No *n/a* The scope of the assigned variable: \'parent\',\'root\' or \'global\'
**Option Flags:**
Name Description
--------- -----------------------------------------------------
nocache Assigns the variable with the \'nocache\' attribute
{$name='Bob'}
The value of $name is {$name}.
The above example will output:
The value of $name is Bob.
{$running_total=$running_total+$some_array[row].some_value}
{$user.name="Bob"}
{$user.name.first="Bob"}
{$users[]="Bob"}
Variables assigned in the included template will be seen in the
including template.
{include file="sub_template.tpl"}
...
{* display variable assigned in sub_template *}
{$foo}<br>
...
The template above includes the example `sub_template.tpl` below
...
{* foo will be known also in the including template *}
{$foo="something" scope=parent}
{* bar is assigned only local in the including template *}
{$bar="value"}
...
See also [`{assign}`](#language.function.assign) and
[`{append}`](#language.function.append)
@@ -0,0 +1,48 @@
{strip} {#language.function.strip}
=======
Many times web designers run into the issue where white space and
carriage returns affect the output of the rendered HTML (browser
\"features\"), so you must run all your tags together in the template to
get the desired results. This usually ends up in unreadable or
unmanageable templates.
Anything within `{strip}{/strip}` tags are stripped of the extra spaces
or carriage returns at the beginnings and ends of the lines before they
are displayed. This way you can keep your templates readable, and not
worry about extra white space causing problems.
> **Note**
>
> `{strip}{/strip}` does not affect the contents of template variables,
> see the [strip modifier](#language.modifier.strip) instead.
{* the following will be all run into one line upon output *}
{strip}
<table border='0'>
<tr>
<td>
<a href="{$url}">
<font color="red">This is a test</font>
</a>
</td>
</tr>
</table>
{/strip}
The above example will output:
<table border='0'><tr><td><a href="http://. snipped...</a></td></tr></table>
Notice that in the above example, all the lines begin and end with HTML
tags. Be aware that all the lines are run together. If you have plain
text at the beginning or end of any line, they will be run together, and
may not be desired results.
See also the [`strip`](#language.modifier.strip) modifier.
@@ -0,0 +1,43 @@
{while} {#language.function.while}
=======
`{while}` loops in Smarty have much the same flexibility as PHP
[while](&url.php-manual;while) statements, with a few added features for
the template engine. Every `{while}` must be paired with a matching
`{/while}`. All PHP conditionals and functions are recognized, such as
*\|\|*, *or*, *&&*, *and*, *is\_array()*, etc.
The following is a list of recognized qualifiers, which must be
separated from surrounding elements by spaces. Note that items listed in
\[brackets\] are optional. PHP equivalents are shown where applicable.
Qualifier Alternates Syntax Example Meaning PHP Equivalent
-------------------- ------------ ------------------------ -------------------------------- ----------------------
== eq \$a eq \$b equals ==
!= ne, neq \$a neq \$b not equals !=
\> gt \$a gt \$b greater than \>
\< lt \$a lt \$b less than \<
\>= gte, ge \$a ge \$b greater than or equal \>=
\<= lte, le \$a le \$b less than or equal \<=
=== \$a === 0 check for identity ===
! not not \$a negation (unary) !
\% mod \$a mod \$b modulous \%
is \[not\] div by \$a is not div by 4 divisible by \$a % \$b == 0
is \[not\] even \$a is not even \[not\] an even number (unary) \$a % 2 == 0
is \[not\] even by \$a is not even by \$b grouping level \[not\] even (\$a / \$b) % 2 == 0
is \[not\] odd \$a is not odd \[not\] an odd number (unary) \$a % 2 != 0
is \[not\] odd by \$a is not odd by \$b \[not\] an odd grouping (\$a / \$b) % 2 != 0
{while $foo > 0}
{$foo--}
{/while}
The above example will count down the value of \$foo until 1 is reached.
See also [`{foreach}`](#language.function.foreach),
[`{for}`](#language.function.for) and
[`{section}`](#language.function.section).