- ^ Jelix components
- jTpl, template engine
- Zones
- jDao: relational object mapping
- Classic forms
- jForms: automatic forms
- jDb: accessing to SQL database
- jKVDb: accessing to key/value databases
- jUrl: automatic urls
- jAuth : authentication system
- jAcl2 : rights management
- jLocale: localization
- jEvents: communication between modules
Chapter: jTpl, template engine
^ Jelix components | Zones » |
− Table of content
Jelix includes its own template engine, jTpl, bases on the template engine
Castor. Templates are files with the ".tpl"
extension and located in the templates
directory of modules.
The jTpl object ¶
The jTpl
object is meant to generate the content specified in a template
file, with data input by you, following the instructions in the template.
Some of jResponse*
objects or jZone
instanciate for you a jTpl
object. For example the body
property of the jResponseHtml
object is
a jTpl
object, as for the _tpl
property of jZone
.
In other case, you have to instantiate a jTpl
:
$tpl = new jTpl();
Here are the most important methods to know.
assign ¶
$tpl->assign($name, $value);
This method allows you to create a template variable. A template variable is only accessible in the template level. You will then use this method to pass data (static values, objects, iterators, etc) to the template to be able to use it for content generation.
You can also create or modify a variable directly in the template, using:
{assign $name = $value}
- *Important** : the name of a template variable should follow syntaxic rules for a name of a PHP variable. The name should contain only letters, numbers or "_".
assignByRef ¶
Same purpose of the assign
method, but the value is passed by reference,
so you can assigne huge array without duplicating them in memory.
assignIfNone ¶
Same purpose of the assign
method, but the value is assigned only if the
variable doesn't exist.
assignZone ¶
$tpl->assignZone($name, $zoneSelector, $params);
The $params parameters is optional. This method is a shortcut for:
$tpl->assign($name, jZone::get($zoneSelector, $params));
assignZoneIfNone ¶
Same as assignZone
, but the content of the zone is assigned only if the
variable doesn't exist.
get ¶
If you want to get the value of a template variable that is already initialized, you can use this method :
$value = $tpl->get('foo');
Generating the content ¶
After variables are created and initialized, you can call the fetch
method
to generate the content of the template, and to retrieve it. You give the
selector of the file template as the first parameter.
$content = $tpl->fetch('mymodule~mytemplate');
You call this method only if you have instanciate the jTpl object. In other case, you needn't to call it.
There is an other method you won't never call, since jResponse objects use
it: display
.
$tpl->display('mymodule~mytemplate');
It generates the content and output it directly.
Template files ¶
A template file is made of HTML, XML or whatever you want if it corresponds to the type of the response. It contains also some instructions to incorporate values that you will define, instructions to repeat the generation of parts of HTML, etc.
The syntax used in jTpl is a mix of the one used in smarty and the PHP syntax. The goal is to have templates readable enough, easy to modify and not forcing a syntax that is too different from PHP. All this proposing features that PHP doesn't have and adapted to Jelix.
Do not forget that most of the templates that you will make shouldn't be entire
files. Especially for the HTML responses, your templates must contain only what
is between the <body>
and </body>
tags, the rest is automatically
generated thanks to jResponseHtml
.
Instruction syntax ¶
Instructions in jTpl are specified between curly braces : {instruction ...}
If you want to include curly braces in your template, outside of a jTpl
instruction, you can use {ldelim}
for "{", or {rdelim}
for "}".
If you have a block with several curly braces, like in a piece of code of
javascript, you can use {literal}
instead of {ldelim}
or {rdelim}
.
<script type="text/javascript">
{literal}
for(i=0;i<max;i++) {
if(foo){ ...}
}
{/literal}
</script>
If you want to put comments which won't be include in the resulting content, use {*...*}
<p>bla bla</p>
{* this is a comment *}
You can write an instruction on several lines:
<div>
{zone
'foo~bar',
array(
'foo1'=>$foo1,
'foo2'=>$foo2)}
</div>
Expressions ¶
A jtpl expression is identical to a PHP expression, and return a value, like in PHP. You can use classical PHP operators, objects, array etc. You can use also template variables, like any PHP variables. You use jtpl expressions as arguments of jtpl instructions. Here is a simple expression:
$template_variable
An expression can also contain some selector of locales, by using a specific syntax. This selectors should be introduced between two "@".
@my_module~key.localized.string@."fooo bar"
It is equal to this PHP code :
jLocale("my_module~key.localized.string")."fooo bar"
Inside a locale key, you can use some template variables. It allows to construct dynamically a locale key:
@my_module~key.$variable.string@."fooo bar"
It is equal to this PHP code :
jLocale("my_module~key.".$variable.".string")."fooo bar"
Displaying an expression, a variable ¶
To display the result of an expression, you should put it between curly braces. The first element of the expression should be a variable or a locale selector.
{$myvariable}
{$myvariable * 3}
{$myvariable." - ".@mod~message.ok@}
{@modul~a.key.of.locale@."-".$anOtherVariable}
{@modul~a.key.$dynamique@."-".$anOtherVariable}
This is equal to
<?php echo $myvariable; ?>
<?php echo $myvariable * 3; ?>
<?php echo $myvariable." - ".jLocale::get("mod~message.ok"); ?>
<?php echo jLocale::get("modul~a.key.of.locale")."-".$anOtherVariable; ?>
<?php echo jLocale::get("modul~a.key.".$dynamique)."-".$anOtherVariable; ?>
For more complex expressions , you can use the syntax with =
:
{=$myvariable}
{=intval($myvariable) * 3}
Predefined constants ¶
Some variables are predefined so you have not to assign them:
- $j_basepath: it contains the url path of the directory of the application (this is the value of the parameter "basePath" in the configuration)
- $j_jelixwww: it contains the url path of the directory
jelix-www/
(this is the value of the parameter "jelixWWWPath" in the configuration) - $j_themepath: it contains the url path of the directory of the current theme in www
- $j_datenow: current date (aaaa-mm-jj)
- $j_timenow: current hour (hh:mm:ss)
- $j_locale: current locale code (the value of
jApp::config()->locale
) - $j_lang: current lang code
- $j_country: current country code
- j_assetsRevision: the value of the configuration parameter
assetsRevision
- j_assetsRevisionParameter: the value of the configuration parameter
assetsRevisionParameter
- j_assetsRevQueryUrl: the part to add to an url for assets revision (concatenation of
assetsRevisionParameter
,=
andassetsRevision
)
Modifiers ¶
A modifier is a function which modify the output of an expression. You can use many modifiers at the same time. It works in fact like modifiers of Smarty:
{$avariable|upper}
{$avariable|upper|escxml}
{$aUrl|escurl}
It is equal to:
<?php echo strtoupper($avariable);?>
<?php echo htmlspecialchars(strtoupper($avariable));?>
<?php echo rawurlencode($aUrl);?>
Some modifiers, like those in the previous example, are simple aliases to some native PHP functions:
- upper (strtoupper)
- lower (strtolower)
- escxml and eschtml (htmlspecialchars)
- strip_tags (strip_tags)
- escurl (rawurlencode)
- capitalize (ucwords)
- stripslashes (stripslashes)
- upperfirst (ucfirst)
Many others are function defined in plugins for jTpl. See the list in the API reference
Modifiers with parameters ¶
Some modifiers need some parameters. You should put this parameters after a ":" after the modifier name, and you should separate parameters with ",". Parameters are expressions.
Example with the jdatetime modifier:
<p>The date is {$myDate|jdatetime:'db_date','timestamp'}.</p>
Escaping content ¶
By default content variables are inserted as is into the generated content. This may be not
what you want. You would escape some characters, like <
and >
in HTML, so the browser
will not perform these characters as tags.
So you should escape content variable:
- by using the
eschtml
orescxml
modifier:{$myvar|eschtml}
- or by activating the auto-escaping: add a
{! autoescape !}
tag at the beginning of your template. All output of variables (with a tag{$..}
) will be escaped.- If there is already an
eschtml
modifier, it will not add an additionnal escape process. - If you don't want to escape a variable, use the
raw
modifier:{$myHTMLcontent|raw}
- If there is already an
Control statements ¶
They are similar to statements of PHP, except that parenthesis are not required around conditions or expressions.
if, else, elseif ¶
{if condition_1}
// code here
{elseif condition_2}
// code here
{else}
// code here
{/if}
Note that some plugins are provided and are specific conditional statements,
like ifacl2 'a.right'
. You can use the else
statement for all of them
begining by "if".
while ¶
{while condition}
// code here
{/while}
foreach ¶
{foreach $iterator_or_array as $key=>$value}
// code here
{/foreach}
for ¶
{for expression}
// code here
{/for}
The expression should be identical as the expression of the for
in PHP.
break ¶
You can use {break}
to insert a break
instruction into a loop:
{while condition}
...
{if ...} {break} {/if}
....
{/while}
Functions ¶
Functions in a template are plugins you can use in a template. This plugins are simple PHP functions and you can create some kind of plugins.
The syntaxe of the call in a template is:
{function_name expression, expression,...}
You mustn't use parentheses around all parameters. Expressions are jtpl expressions, so similar to PHP expressions.
Note that some functions and other template plugins are callable in general only in a template used by a specific type of response. Some plugins are for HTML responses, some other plugins are for text responses.
Personalized functions and modifiers ¶
If you want to have some new jtpl functions or modifiers, you can realized some plugins. See the documentation about it. This is simple.
An other solution is to declare the modifiers or the functions dynamically, by
calling the jtpl methods registerModifier()
or registerFunction()
.
To this methods, you should indicate a name which will used in the template, and
a name of a php function which implements the modifier or the function. The
arguments of the php function are the same of the php function of a jtpl plugin.
Meta informations ¶
There is a special tag: {meta}
. It doesn't change how the template is
generated, it doesn't generate some content, and more important, it cannot be
influenced by any other template instructions. Putting it inside an "if"
statement for example, does nothing. The meta tag will be interpreted, even if
the if statement is false. The meta tag exists only to provide informations for
the code which uses the jtpl object.
The syntax is
{meta name expression}
Example:
{meta author 'laurent'}
You can create all meta you want. Then this informations are available in the
jTpl
object, by using the meta
method.
$tpl = new jTpl();
$metas = $tpl->meta('mymodule~thetemplate');
$metas['author']; // contains 'laurent'
Note: if you use a variable in the expression of a meta tag, this variable
should be assigned from the jtpl object, not from other instruction in the
template itself (like {assign ...}
).
Advanced meta informations ¶
Another type of meta tag allows you to automatically process meta data. Those are implemented through template plugins.
Their syntax is:
{meta_//plugin_name// name expression}
Example which uses the meta_html plugin. This plugin allows to modify the current html response: it can add a css stylesheet, a javascript link etc.
{meta_html css '/styles/my.css'}
{meta_html js 'fooscript.js'}
{meta_html bodyattr array('onload'=>'alert("charge")')}
Including a template into an other ¶
There is some case where you would like shared contents of a template with other
templates. To do it, you will create a template file, and use the {include}
tag inside the template which will include the other template. You should give
the selector name.
<div>
...
{include 'mymodule~sharedcontent'}
</div>
All template variables declared in the jtpl object will be accessible into the included template.
If you don't want to share variables into the included template, you should use
the {fetchtpl}
tag. It is useful to include a template recursively.
<div>
...
{fetchtpl 'mymodule~sharedcontent'}
</div>
Before using the {include}
or {fetchtpl}
tag, first consider using
zones. In many case, it is better, because its generated
content may be stored in a cache.
Macros ¶
In a template, you may want to repeat a piece of template without using a loop. You could include several time an other template, but for little piece of template, this slower than the use of a macro.
A macro is a part of a template declared with the {macro}
tag. A macro have a
name and it is like a function in PHP.
Example of the declaration:
{macro 'myblock'}
<p>This is a block, displaying the value of $val: {$val}</p>
{/macro}
The name is set using the syntax of a PHP string. Variables or any other language syntax are not allowed.
Variables used inside the block can be variables declared into the template. The scope is global. You can use any template plugin, statements etc.
To call a macro, use {usemacro}
:
This is my piece of html:
{usemacro 'myblock'}
...
I can display my piece of html again:
{usemacro 'myblock'}
If $val
equals 'hello'
, the results will be :
This is my piece of html:
<p>This is a macro, displaying the value of $val: hello</p>
...
I can display my piece of html again:
<p>This is a macro, displaying the value of $val: hello</p>
You can declare parameters to a macro. Indicate parameters like for a PHP function (i.e. $foo
), and
use parameters inside the macro like any other variables.
{* declaration of the macro *}
{macro 'myblock', $name, $result}
<p>This is a macro with parameters.<p>
<ul>
<li>name= {$name}</li>
<li>{if $result == true}this is green{else}this is red{/if}</li>
</ul>
<p>You can still see the value of $val: {$val}</p>
{/macro}
{* usage of the macro *}
{usemacro 'myblock', 'SuperGuppy', true}
Declared parameters are not usable outside the macro. If there is a template variable with the same name, the value of the template variable is replaced by the value of the parameter inside the macro, but is restored after the call of the macro.
Macro declared into an included template can be used in the template caller.
Virtual Templates ¶
You can use templates that are not in files. These are called "virtual templates". Typically, you have a template in a string (retrieved from a database for example), and then you can generate the content into a string.
A simple example :
$template = ' hello
{$value}
world
{for $i=1;$i<=5;$i++}
{$i}
{/for}';
$tpl = new jTpl();
$tpl->assign('value', 'test');
$content = $tpl->fetchFromString($template, 'text');
As second argument, you can indicate the type of content (text
, html
...).
$content
will be:
hello
test
world
1
2
3
4
5
You can then inject this content into an other template for example.
Templates dedicated to a locale ¶
In a template, we saw that we can use {@foo.bar@}
to include localized string.
However, you can have many localized string, and so the template is less
readable, and performance are lower.
There is a solution: create templates for each language. Of course, it means that you duplicate the code of the template, and so it is less easy to maintain them. So you should think if you prefer performance or easy modifications...
To create a template for each language, create sub-directories into the template
directory. Their name should be a language code. Example: templates/fr_FR
,
templates/en_US
etc. And save in each of this sub-directories a copy of
your translated template.
Redefining a template ¶
Each module defines some template. If the module comes from an other project, or is shared by other application, you shouldn't modify the template, because each time you want to update this module, you should take car to not erase your modifications.
Fortunately, Jelix provide a system of theme, so you can redefine template without modify the original files.
The default theme is in the directory app/themes/default/
. So the
app/themes/default/my_module/my_template.tpl
redefines the template
my_module/templates/my_template.tpl
For more details, see the chapter on themes
Inside the template engine ¶
Jtpl templates are "compiled". Jtpl convert template to PHP files, and this php
file are stored in the cache to increase performances. You can see them in
temp/your_appname/compiled/templates/modules/your_module~your_template.php
,
or for templates included in themes, look in
temp/your_appname/compiled/templates/themes/theme_name/your_module~your_template.php
You can create your own plugin template, if you have particular needs or want to use your own tag(s) in a template. See /plugins/tpl