Smarty FAQs

There should be plenty of these knocking around on the smarty-general mailing list. Post them here, with or without an answer

Index

  • [1] What's a template engine and why should I use one?
  • [2] What does template compilation mean anyway? (redemption)
  • [1] How do you use Smarty with an ISP running PHP 4.2.1 with safe_mode on?
  • [2] Any tips for installing Smarty with Apache on Windows?
  • [3] How should I best arrange my template folders so that editing templates in a WYSIWYG app still gets access to image files?
  • [4] Is there a NOT usable way to configure Apache/PHP to run Smarty template files directly instead of calling a php file?
  • [5] How do I fix the Call to undefined function error?
  • [6] Something's gone wrong! I wrote the template, wrote the PHP code, included Smarty.class.php, intialized object, etc... But one of my templates doesn't produce any output! There are no error messages too!
  • [1] How do I count the number of elements in an array?
  • [2] How can I use different delimiters for the Smarty syntax in my templates?
  • [3] Is there a way to escape '{' and '}' in html? I need to put on my page style definition - which is enclosed in {}, but do not want to change standard delimiter ?
  • [4] In the table I am creating, I want to create an sequence of table rows with diferent styles, e.g. style0, style1, style2, style0. Normally I would use the % operator to get the remainder when the rownumber is divided by 3 but that doesnt seem to work, what is the correct way to produce a sequence like 0,1,2,0,1,2 in smarty?
  • [5] How can I access an indexed array with an index from a associative array?
  • [6] How can I concatenate $smarty.get.foo and $smarty.get.bar and assign the result to $baz?
  • [7] Is it possible to do {include file={$smarty.get.var}}?
  • [8] How can I use Smarty variables as PHP variables like {php} print_r({$var}); {/php}?
  • [9] Is it possible to stop the display of a template with a tag inside the template, outputting only what has been reached so far?
  • [10] How can I do a simple for loop?
  • [11] How can I display the results of class methods (or functions)? (I.e., I have a method called $system->getUsername($uid) that returns a username.)
  • [12] How could I iterate easily over an array?
  • [13] Is there an elegant way to automatically format a list of items into three or more columns?
  • [14] Can I use the template_dir and compile_dir from inside the template without assigning it first?
  • [15] How can I determine whether a given element is an array or a scalar?
  • [16] How can I assign a variable in an include file and have it visible to the original template?
  • [17] PHP Error Reporting level is set to E_ALL and smarty throws "undefined index"-errors. What can I do?
  • [18] How can I call methods of a class that was returned by an assigned object?
  • [19] How can I assign a template array during the execution of the template?
  • [20] How could I access an arrayvalue in a functioncall?
  • 21. How can I loop data but ordering it by date or name instead of ID? UNANSWERED
  • 22. How to define constants? UNANSWERED
  • 23. How can utilize a foreach loop to display table header column names only once? I get an error when attempting to use the iteration variable within an {if} statement. An alternative to the following code would be helpful. UNANSWERED
  • [24] Where is the 'next' or 'continue' in Smarty's loops, to skip to the next iteration?
  • [1] How can I create a closing-tag plugin (Like {mytag}blah{/mytag})?
  • [2] My filter plugins never seem to get called unless I explicitly register them.
  • [1] Is it possible to access Smarty config files directly from PHP scripts?
  • [2] How do I add a value with line breaks to a config file?
  • 3. Aren't config file variables supposed to be statically written in the template, so that you can create several compiled version, one for each language by instance with a NULL overhead? UNANSWERED
  • [4] How do I define a config file variable as an array?
  • [1] How do you get data from a database when you have used a class to make the connection? I just get nothing displayed and it doesn't loop.
  • [2] I have content in the memory I want to use as smarty template. Must I create a file from it?
  • [3] I can't seem to get the template_exists function to work correctly, what might be the correct syntax for it?
  • [4] Can I force Smarty to store compiled templates into database rather than file on the disk?
  • [5] Is there anyway to send the compiled template code to a variable instead of $smarty->display() that output's it ? (I want to create a template for mail e.g)
  • [6] How should I ask Smarty to display a page incrementally i.e. one that takes a long time to generate?
  • [7] Is there an instruction to get all vars assigned to a template?
  • [8] Is there a way to use ONE template directory for a site with multiple directories?
  • [9] Is there a way designers can view all assigned vars?
  • [10] Is there a way programmers can access all vars in a template file through PHP?
  • [11] How come the date_format modifier doesn't work right?
  • [12] Is there anything I should know about using Smarty with my custom error handler?
  • [1] How do I configure Dreamweaver to recognize Smarty template (.tpl) files?
  • [2] Is there a Smarty edit mode for jEdit?
  • [1] Can I create a proprietary software, and sell it with Smarty?
  • [2] Is there a tutorial on how to create XML using Smarty? Partially ANSWERED
  • [3] How do I assign function results?
  • [4] What is this GoldStar? thing all about? I found a GoldStar? on my Entry??
  • [5] Why is it called Smarty? Who came up with such a name?
  • [6] Why isnt capitalize working properly with special chars, such as the swedish ?

Basics

Q: What's a template engine and why should I use one?

A: (copied from Smarty manual)

Smarty is a template engine for PHP. More specifically, it facilitates a managable way to separate application logic and content from its presentation. This is best described in a situation where the application programmer and the template designer play different roles, or in most cases are not the same person. For example, let's say you are creating a web page that is displaying a newspaper article. The article headline, tagline, author and body are content elements, they contain no information about how they will be presented. They are passed into Smarty by the application, then the template designer edits the templates and uses a combination of HTML tags and template tags to format the presentation of these elements (HTML tables, background colors, font sizes, style sheets, etc.) One day the programmer needs to change the way the article content is retrieved (a change in application logic.) This change does not affect the template designer, the content will still arrive in the template exactly the same. Likewise, if the template designer wants to completely redesign the templates, this requires no changes to the application logic. Therefore, the programmer can make changes to the application logic without the need to restructure templates, and the template designer can make changes to templates without breaking application logic.

Q: What does template compilation mean anyway? (redemption)

A: What do web pages have to do with compiling? Isn't compiling something C++ and Java programmers do? Well, this is a different sort of compilation. Smarty parses your templates and creates PHP scripts from them (instead of binaries as in general programming). When your web page is viewed, Smarty reads from these PHP scripts instead, saving the work of having to parse your templates again. Smarty is smart about when to compile too: it only re-compiles your templates when you make changes to them so you don't have to worry about manually compiling your templates.

Installation

Q: How do you use Smarty with an ISP running PHP 4.2.1 with safe_mode on ? (rgittens)

A: Set $use_sub_dirs to false in Smarty.class.php.

Q: Any tips for installing Smarty with Apache on Windows? (gdh)

A: A complete 'Smarty on Windows' solution, by David...

Smarty Rocks! This information relates to running Smarty with Apache and PHP on Windows XP.

The script (below) can equally be used on Linux. You simply change the directory constants,

and use forward slashes instead of backslashes. In fact, I write and test code on my WinXP?? PC

at home, but my website is running on a Linux server! :D

1. The obvious: Download and install a web server (e.g. Apache), and PHP.

2. The next obvious thing: Download and Unzip Smarty.

3. Rename Smarty's folder as 'smarty' (Mine unzipped as 'Smarty-2.6.2'.)

4. Copy-Paste or Cut-Paste the Smarty directory to the same base folder where your web root is.

(This adds security by putting Smarty outside of your *public* web root.)

e.g. My web root is 'D:\apache\Apache2\htdocs\'

My Smarty root is 'D:\apache\Apache2\smarty\'

5. Setup Smarty.

The version of Smarty I downloaded (2.6.2) keeps its code in the 'libs' directory.

It also has a 'demo' directory that contains the 'templates', 'templates_c', and 'configs' directories.

Rename or Copy-Paste-Rename the 'demo' directory (Mine is called 'gnd'). These are *your* template directories!

6. Create a script that sets up a 'Smarty connection'.

You can re-use this script by calling require_once('smarty-winxp.php') from other scripts.

Take a look at the (well-commented) code below to see how I use Smarty in my scripts:

(Er... sorry -- I had to add // before hashed comments to make them appear properly. This is my first Wiki.)

<?php

//############################################################

//# smarty-winxp.php

//# -- Sets up a connection with the Smarty template engine.

//#

//# Usage: require_once('smarty-winxp.php') in a script.

//#

//# Author: David Redstone

//# Email: David X-AT-X inglesisimo X-DOT-X com

//#

//############################################################

//######################################################################

//# Create constants to represent Smarty's directory, and my directory

//# (Notice that for security, Smarty resides outside

//# of Apache's web root, which is 'Apache2\htdocs'.)

//######################################################################

define(SMARTY_DIR,'D:\\apache\\Apache2\\smarty\\libs\\'); // Note: You have to 'escape' backslashes, hence: 1< define(MY_DIR,'D:\\apache\\Apache2\\smarty\\gnd\\');

//#######################################

//# Use Smarty.class.php in this file.

//#######################################

require_once(SMARTY_DIR.'Smarty.class.php');

//##############################

//# Create a new Smarty object

//##############################

$smarty = new Smarty;

//###################################

//# Setup some of Smarty's options.

//###################################

$smarty->compile_check = true;

$smarty->debugging = true; Uncomment this if you want to see the debugging window pop up when you call a template!

//###########################################################

//# Setup the Smarty template engine's directory structure.

//# (gnd is my personal project directory!)

//###########################################################

$smarty->template_dir = MY_DIR.'templates';

$smarty->compile_dir = MY_DIR.'templates_c';

$smarty->config_dir = MY_DIR.'configs';

?>

Well, that's it! I really hope it helps someone. The previous answer wasn't *complete* enough for me.

A:

see also: [this forum post]

(Corrected by pk)

Here's a few - Start with [Apache] and [PHP] first, (obviously) then...

1) Download the source [here]

2) Unzip to E:\ (new folder will be named smarty2.3.1 - rename it to Smarty, so the path is E:\Smarty\ - You may have to use C: or D: etc. - anywhere outside htdocs)

3) Copy E:\Smarty\index.php to \htdocs\yourapp\index.php

4) If you haven't already done so, edit apache's http.conf as follows:

...add "index.php" onto the end of your DirectoryIndex setting (separate each entry with a space.) (copied from [here].)

5) Edit \htdocs\yourapp\index.php so the top looks like this:

<?php

define('SMARTY_DIR','E:\\Smarty\\');

require(SMARTY_DIR.'Smarty.class.php');

$smarty = new Smarty;

$smarty->template_dir = 'E:\\Smarty\\templates';

$smarty->compile_dir = 'E:\\Smarty\\templates_c';

$smarty->config_dir = 'E:\\Smarty\\configs';

// end-snip rest of index.php below

This method lets you skip the step of adding E:\Smarty to the php-include path.

6) View http://localhost/yourapp/ in your browser. You should see the samples in index.php.

Remember that you have to put your templates into E:\Smarty\templates if you use this way.

Instead of \\ in the path names you could also use / (e.g. E:/Smarty/templates)

----------

(Note from DF)

Regarding the original post, I was getting a "Use of undefined constant SMARTY_DIR...etc" until I changed these two lines:

define(SMARTY_DIR,'D:\\apache\\Apache2\\smarty\\libs\\'); // Note: You have to 'escape' backslashes, hence: 2< define(MY_DIR,'D:\\apache\\Apache2\\smarty\\gnd\\');

to

define('SMARTY_DIR','D:\\apache\\Apache2\\smarty\\libs\\'); // Note: You have to 'escape' backslashes, hence: 3< define('MY_DIR','D:\\apache\\Apache2\\smarty\\gnd\\');

Notice the single quotes now around SMARTY_DIR and MY_DIR.

I don't know what that's about, I just know it got rid of the error.

Q: How should I best arrange my template folders so that editing templates in a WYSIWYG app still gets access to image files?

A: I created an [Output Filter] with a regular expresion, which replaces all SRC="./picture.jpg" with my imagepath

This is the Filter for it:

function editImagePath($tpl_source, &$smarty)

{

$pattern = '=(<img\s+src\s*\=\s*")()=i';

$tpl_source = preg_replace($pattern, '\\1'.$smarty->imagepath, $tpl_source);

$pattern = '=(<(td|tr|body)\s+background\s*\=\s*")()=i';

$tpl_source = preg_replace($pattern, '\\1'.$smarty->imagepath, $tpl_source);

return $tpl_source;

}

$smarty->imagepath="templates/";

$smarty->register_outputfilter('editImagePath');

$smarty->display('index.tpl');

That's it, good luck! Cy

Q: Is there a usable way to configure Apache/PHP to run Smarty template files directly instead of calling a php file (boots) ?

This seems to be the best answer of all that have been given:

A #4: (Scott Matthewman) One way is to assign a custom handler and action. Give your template files a unique file extension (for example, '.smarty'), and add the following Apache directives to an .htaccess file or your httpd.conf:

AddHandler?? smarty-template .smarty

Action smarty-template /path/to/parser.php

(Note that the path to the parser file is from the web root, not from the process root.)

When you reference a URL to a .smarty file, parser.php gets called instead, with the absolute path to the requested template file available as $_SERVER['PATH_TRANSLATED'];

One thing you have to bear in mind is that as long as the request path ends in your specified extension, your parser file may get called even if the specified file doesn't actually exist, so you should always use the file_exists() function to check your $_SERVER['PATH_TRANSLATED'] value before attempting to use it.

Other answers to this question:

A #1: (boots) I suspect that I can write a php prepend that acts as a template loader. I haven't played with those things before: am I off-track?

A #3: (toma) I suspect you can get something that works in the auto_prepend_file but I don't think it's a good idea. Tim's idea below will work but it relies on the templates to be visible from the web directly, which I think is a bad idea. One alternative is implementing an index.php file (the same way this wiki does) to show whatever template was passed in the $page get variable.

A #2: (Tim Strehle) A quite simple way would be to save your template files with the .php extension, put a

<?php require('init.inc.php'); ?>

into the first line of every template, then do all the initialization stuff in init.inc.php:

<?php

require_once('Smarty.class.php');

$self = $DOCUMENT_ROOT . $PHP_SELF;

$tpl = new Smarty;

$tpl->template_dir = dirname($self);

$tpl->compile_dir = $tpl->template_dir . '/.smarty/templates_c';

$tpl->config_dir = $tpl->template_dir . '/.smarty/configs';

$tpl->cache_dir = $tpl->template_dir . '/.smarty/cache';

$tplname = basename($self);

$cacheid = '';

if (! $tpl->is_cached($tplname, $cacheid))

{ $tpl->assign('NAME', 'fred');
}

$tpl->display($tplname, $cacheid);

exit;

?>

Q: How do I fix the 'Call to undefined function: ()' error?

A: One possible cause of this problem is Smarty trying to use some code from a plugin when the plugin has not been loaded properly. Check the permissions on your plugins directory.

Q: Something's gone wrong! I wrote the template, wrote the PHP code, included Smarty.class.php, intialized object, etc... But one of my templates doesn't produce any output! There are no error messages too !

A: Check permissions to your template file. It should be world readable (try to chmod a+r mytemplate.tpl)

A: You might also have PHP set to display no error messages or warnings. Check error_reporting variable setting. You might also change it from PHP using ini_set()

Template Design

Q: How do I count the number of elements in an array?

A:

{$array|@count}

The "@" applies the modifier directly to the array instead of each individual element.

Q: How can I use different delimiters for the Smarty syntax in my templates ?

A: The delimiter settings are in variables of the Smarty object, change them in the PHP code.

$t = new Smarty;

$t->left_delimiter = '<!--{';

$t->right_delimiter = '}-->';

Q: Is there a way to escape '{' and '}' in html? I need to put on my page style definition - which is enclosed in {}, but do not want to change standard delimiter ?

A: (sam) Use {literal}this is your code with your { and }'s :-){/literal}.

Quote from Smarty Manual: 'Literal tags allow a block of data to be taken literally, not being interpreted by the Smarty engine. This is handy for things like javascript sections, where there maybe curly braces and such things that would confuse the template parser.

Anything within {literal}{/literal} tags is not interpreted, but displayed as-is.'

{literal}

<script language="JavaScript??" type="text/javascript">

function myFunc() {

alert('Hello World!');
}

</script>

{/literal}

If you need Smarty vars inside the script use something like this:

{literal}

<script language="JavaScript??" type="text/javascript">

function myFunc() {

alert('{/literal}{$myVar}{literal}');
}

</script>

{/literal}

Escaping individual delimiters with {ldelim}{rdelim} instead of the entire block may work cleaner for imbedding:

<script language="JavaScript??" type="text/javascript">

function myFunc() {ldelim}

alert('{$myVar}');

{rdelim}

</script>

A: (jason) Use &#123; and &#125; for { and }, respectively. Ensure this works with your character set.

Q: In the table I am creating, I want to create an sequence of table rows with diferent styles, e.g. style0, style1, style2, style0. Normally I would use the % operator to get the remainder when the rownumber is divided by 3 but that doesnt seem to work, what is the correct way to produce a sequence like 0,1,2,0,1,2 in smarty?

A: Have a look at [cycle]. It does the trick with no pain!

Q: How can I access an indexed array with an index from a associative array?

A: Since Smarty-2.6.0 you can do the following for simple cases:

{$indexed_array[$associative_array.index_field]}

For more complex cases, for example if your key is a string containing a space, as in

$myarray['one two'];

you'll need the following:

{assign var=key value='one two'}

{$myarray.$key}

Q: How can I concatenate $smarty.get.foo and $smarty.get.bar and assign the result to $baz?

A: If you try the following

{assign var="baz" value="$smarty.get.foo:$smarty.get.bar"}

you will receive broken output. Likewise for combining these with ->, [], etc. This seems to be an implementation limitation and the only way around it seems to consist of assigning the multi-level descriptor to a short variable name first:

{assign var="get_foo" value=$smarty.get.foo}

{assign var="get_bar" value=$smarty.get.bar}

{assign var="baz" value="$get_foo:$get_bar"}

You could also use a custom plugin to concatenate string:

/*

* Smarty plugin

* -------------------------------------------------------------

* Type: modifier

* Name: concat

* Purpose: concatinates two strings

* -------------------------------------------------------------

*/

function smarty_modifier_concat($string, $concat)
{

return $string.$concat;
}

Here's a example:

{$smarty.get.foo|concat:$smarty.get.bar}

A: (zer0fill) You can also use the back-tick (`) method

<{assign var=concat value=`$smarty.get.action``$smarty.post.mode`}>

A: Note: As of version 2.6.9 (and perhaps earlier) there is a custom modifier that comes pre-installed for this purpose. It is called simply "cat".

So, usage would be:

{$smarty.get.foo|cat:$smarty.get.bar}

This variable modifier is not mentioned in the 2.0 docs. You may want to take a look at your libs/plugins directory to see if there are other goodies that the docs aren't telling you about.

Q: Is it possible to do: {include file={$smarty.get.var}}?

A: (Josh Johnson) When you specify a smarty variable, even the special $smarty.get

variable, inside of another template function (like include), you

just drop the delimiters ({}), so it would be:

{include file=$smarty.get.var}

Q: How can I use Smarty variables as PHP variables like {php} print_r({$var}); {/php}?

It is legitimate to access variables via the $this->_tpl_vars[variable name], since _tpl_vars is the internal array containing Smarty variables. (Or $smarty->_tpl_vars etc., depending on which variable is in scope.)

Q: Is it possible to stop the display of a template with a tag inside the template, outputting only what has been reached so far?

A: Yes. Create a compiler plugin called "return" which outputs a PHP return statement.

Compiler plugin:

/*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     compiler.return.php
 * Type:     compiler
 * Name:     return
 * Purpose:  Return from current template.
 * -------------------------------------------------------------
 */
function smarty_compiler_return($tag_arg, &$smarty)
{
    return "\nreturn;";
}

How to use it:

{if $foobar}{return}{/if}
This will only be shown if $foobar is false.

A: The cleanest way would be a {if} ... {else} ... {/if} function where you decide whether to output the content or not. It's normally not a good idea to break the normal program flow using "goto", "exit", "return" or "die" commands because your code gets more unreadable and is harder to debug. But that's another discussion ... ;-)

Q: How can I do a simple for loop?

A: Use the {section} tag like this:

{section name="myLoop" start=0 loop=6}

index={$smarty.section.myLoop.index}

{/section}

This will output:

index=0
index=1
index=2
index=3
index=4
index=5

Another example:

{section name="myLoop" start=0 loop=5 step=2}

index={$smarty.section.myLoop.index}

{/section}

This will output:

index=0
index=2
index=4

Q: How can I display the results of class methods (or functions)? (I.e., I have a method called $system->getUsername($uid) that returns a username.)

A: Starting with version 2.4.0 you can access object variables and methods from within your template. Here are some short examples:

{$foo->bar}

{if $foo->bar("blah")}

...

{/if}

For more information about object support please checkout the Smarty documenation.

Q: How could I iterate easily over an array? (pk)

A: Your solution would be foreach: (this example iterates about some weblog-comments)

{foreach item=comment from=$comments}

<div class="commenttitle">{$comment.title}</div>

<div class="commenttext">{$comment.text}</div>

{/foreach}

It also uses an associative array, you would have to use this syntax with such an array.

Q: Is there an elegant way to automatically format a list of items into three or more columns?

A: Yes there is, please click to my SmartyColumnsTutorial.

Q: Can I use the template_dir and compile_dir from inside the template without assigning it first?

A: This is not possible.

Q: How can I determine whether a given element is an array or a scalar?

A: {if is_array($element)} .... {else} .... {/if}

Q: How can I assign a variable in an include file, and make it visible to the main (including) template?

(it looks like, in 2.5.0, the 'assign' function works fine but the assigned var isn't visible outside of that file-- is that an implementation limitation?) still problems? http://www.phpinsider.com/smarty-forum/viewtopic.php?p=28930#28930

Q: PHP Error Reporting level is set to E_ALL and smarty throws "undefined index"-errors. What can I do?

A: If you're getting it in a section loop, and especially if smarty's returning a few empty loop products at the end of your loop, it's a bug. Work around it by including your section code in an {if} statement which checks that a value which should not be empty, really isn't empty.

Q: How can I access methods of a class that was returned by an assigned object? For example: {$obj->getMemberObj()->foo()} . I tried to {assign} $obj->getMemberObj() first but that didn't work either.

A: You can't, at least not in PHP4. This is a limitation of the language. In PHP5 this has been solved. Instead, assign the variable first, and then call the function.

{assign var='object' value=$obj->getMemberObj()}

Foo is now: {$object->foo()}

Q: How can I assign a template array during the execution of the template?

A: The only way I was able to do this without employing a custom function was to use explode as a variable modifier. It is quite counter intuitive and there should probably be a better way, but here is how I did it:

{assign var='ArrayName??' value=','|explode:'ElementOne??,ElementTwo,ElementThree??'}

Notice how the value before the pipe is the separator. I imagine that if you wanted to build an associative or multi-dimensional array you would have to employ a custom function or prepare the data in PHP.

---

Here's a simple plugin modifier I used to return a keyed array

{html_options name=pageSize options='25,50,100'|array selected=$pageSize}

// put this in a file: smarty/plugins/modifier.array.php

function smarty_modifier_array($string) {

$array = explode(',', $string);

return array_combine($array, $array);

} //rc

Q: How can I access a value from an array inside of a function?

A: when you try

{html_datedropdown start="1" selected="$Apprenticship.endDay" end="31" name="endeTag"}

it won't work!!! neverless {$Apprenticship.endDay} works fine. You always get .endDay in your function for selected. Afer 2 hour I finaly got this working:

{assign var=key value='endeDay'}

{html_datedropdown start="1" selected=$Apprenticship.$key end="31" name="endeTag"}

but nerver the less I wonder if there is a better way.

A2:

Use backticks around your variable like this:

{html_datedropdown start="1" selected="`$Apprenticship.endDay`" end="31" name="endeTag"}

That worked for me.

Q: How can utilize a foreach loop to display table header column names only once? I get an error when attempting to use the iteration variable within an {if} statement. An alternative to the following code would be helpful.

<form>

<table width=100%>

{foreach name=outer item=customer from=$customers}

{foreach name=inner key=key item=item from=$customer}

<th>{$key|capitalize}</th>

{/foreach}

<tr>

{foreach key=key item=item from=$customer}

<td>{$item}</td>

{/foreach}

</tr>

{/foreach}

</table>

</form>

A: I think this solves your problem and lets you use a seperate variable for header titles and a footer row if you choose (you don't have to)

{* Loop through all the data starting here *}

{foreach from=$tabledata item=rowdatum name=myTable}

{* if we really have data and we are on the first row, start the table *}

{if $smarty.foreach.myTable.first}

<table>

<thead>

<tr class="tableheadrow">

{* do we have explicit titles? if so use them. If not, use the keys! *}

{if $tableheader!=''}

{foreach from=$tableheader name=MyTableUpper? item=headerDatum}

<th>{$headerDatum}</th>

{/foreach}

{else}

{foreach from=$rowdatum name=MyTableUpper? key=headerDatum item=i}

<th>{$headerDatum|capitalize}</th>

{/foreach}

{/if}

</tr>

</thead>

<tbody>

{/if}

<tr class="tablerow{cycle values="1,2"}">

{* Loop through the actual data *}

{foreach from=$rowdatum name=MyTableInner? item=cellDatum}

<td>{$cellDatum}</td>

{/foreach}

</tr>

{* If we are on the last row, close out -- I made it where you can show a footer if you want as well :) *}

{if $smarty.foreach.myTable.last}

</tbody>

{* Do we have a footer? Show it! *}

{if $tablefooter!=''}

<tfoot>

<tr class="tablefootrow">

<td colspan="{$smarty.foreach.myTable.total}" class="tablefooter">{$tablefooter}</td>

</tr>

</tfoot>

{/if}

</table>

{/if}

{/foreach}

Plugin Design

Q: How can I create a closing-tag plugin (Like {mytag}blah{/mytag})?

A: Declare your plugin as a "block function". The function will be called once on the opening tag (to process the attributes) and again on the closing tag (to process the content of the tag). Have a look at [block] in the Smarty documentation.

Q: My filter plugins never seem to get called unless I explicitly register them.

A: (boots) It appears this is by design so that use of the filters can be controlled. It would appear that a way to read templates from a variable would help facilitate the use of filters.

/**

* Smarty plugin

* -------------------------------------------------------------

* File: resource.var.php

* Type: resource

* Name: var

* Purpose: fetches template from a global variable

* Version: 1.0 [Sep 28, 2002 boots since Sep 28, 2002 boots]

* -------------------------------------------------------------

*/

function smarty_resource_var_source($tpl_name, &$tpl_source, &$smarty)
{

global $$tpl_name;

$tpl_source = $$tpl_name;

return true;
}

function smarty_resource_var_timestamp($tpl_name, &$tpl_timestamp, &$smarty)
{

$tpl_timestamp = '';

return true;
}

function smarty_resource_var_secure($tpl_name, &$smarty) { return true; }

function smarty_resource_var_trusted($tpl_name, &$smarty) { return; }

Here is a sample use:

include ('app.start.smarty.php');

$smarty = new Smarty;

// START STAGE 1

include ('plugin/prefilter.macro01.php');

$smarty->register_prefilter("smarty_prefilter_macro01");

$macro = $smarty->fetch("test.tpl");

// START STAGE 2

include ('plugin/prefilter.macro02.php');

$smarty->register_prefilter("smarty_prefilter_macro02");

// use custom template resource "var" to retrieve template from $macro

$smarty->display('var:macro');

Config Files

Q: Is it possible to access Smarty config files directly from PHP scripts? (Peter Kmet)

A: Yes you can use the Config_File class directly (Monte Ohrt):

(corrected by Peter Kmet)

require_once(SMARTY_DIR."Config_File.class.php");

$conf = new Config_File($smarty->config_dir);

/* [2004-06-23]

As of at least Smarty 2.6.2, boolean doesn't exist in Config_File.class.php, but seems to be replaced with booleanize, which is on (true) by default, so this is redundant:

// change yes|true|on and no|false|off to boolean values

$conf->boolean = true;

As above, overwrite is also by default on (true):

// overwrite same named vars, or accumulate array

$conf->overwrite = true;

*/

// get global vars

$foo = $conf->get('english.conf');

// get one global var

$foo = $conf->get('english.conf',null,'var_name');

// get var from section - including 'hidden' sections

$foo = $conf->get('english.conf','section_name','var_name');

// get all vars from given section

$sec_vars = $conf->get('english.conf','section_name');

// get all global vars AND vars from given section

$sec_vars = array_merge($conf->get('english.conf'),$conf->get('english.conf','section_name'));

P.S.(Tom Henry):

Using the above approach WILL allow access to the .Hidden section config vars from your .php file - yet it still preserves them as 'hidden' from access from within the template (.tpl) file - as it appears that this approach does NOT also 'assign' the vars to the template

Addendum (Tom Henry):

A simplified version for accessing vars from the 'global' and 'non-hidden' sections of .conf files - note that this approach also will 'assign' the vars to the template

$smarty->config_load('my.conf'); // optionally: $smarty->config_load('my.conf','Section')

$cfg_vars = $smarty->get_config_vars();

extract($cfg_vars);

Addenum (Monte Ohrt):

When you load a config section from smarty, it combines the global vars with the section vars.

When loading a section directly from Config_File, it only loads the section vars.

If you want the global vars combined, you must do that manually:

// combine global vars with vars from given section

$cfg_vars = array_merge($conf->get('english.conf'),$conf->get('english.conf','mysection'));

Q: How do I add a value with line breaks to a config file?

A: You can put triple quotes around a value in a config file and new lines will be respected:

var = """this

is a multiline

value in a config

file"""

Q: Aren't config file variables supposed to be statically written in the template, so that you can create several compiled version, one for each language by instance with a NULL overhead (katana) ?

Q: How can I define a config file variable as an array? I want to use the same array in multiple templates, so having it defined in a config file seems to make sense.

A: Below is the answer extracted from http://www.smarty.net/forums/viewtopic.php?p=61528

Step 1: Define a function in php file

function configVarToArray($options, &$smarty) {
   // getting the config variable
   $static =& $smarty->get_config_vars( $options['config_var'] );

   // we are seperating it per line.
   $rows = explode( "\n", $static);

   $return=array();
   foreach ( $rows as $line ) {
      // if the line is empty, then skip it
      if ( empty( $line ) )
         continue;
      // we are again seperating each line into two part.
      // everything before [TAB] character is our key,
      // and after it is our value.
      $country = explode ( "\t", $line);
      $return[ $country[0] ] = trim( $country[1] );
   }
   // and now, we transfer our work to standart smarty variable.
   $smarty->assign( $options['array_var'] , $return );
}

Step 2: Register the function in php file

$smarty->config_load("english.conf");	// optionally to load a section: $smarty->config_load("my.conf","Section")
	
// Register the function 'configVarToArray' as 'makeConfigArray' to be accessable from templates
$smarty->register_function('makeConfigArray', 'configVarToArray');

Step 3: Define a config varible in config file "english.conf" (Change "[TAB]" into real TAB character while using)

stable_var_1 = """0[TAB]Select one of them
1[TAB]stuff 1
2[TAB]Stuff 2
3[TAB]Stuff 3
4[TAB]Noting but stuff""" 

Step 4: In the tpl file, use it like this:

{makeConfigArray config_var=stable_var_1 array_var=new_var}
{html_options name=trying options=$new_var}

Step 5: The output

<select name="trying">
<option label="Stuff 1" value="1">Stuff 1</option>
<option label="Stuff 2" value="2">Stuff 2</option>
<option label="Stuff 3" value="3">Stuff 3</option>
<option label="Noting but stuff" value="4">Noting but stuff</option>
</select>

Using Smarty in your Project

Q: How do you get data from a database when you have used a class to make the connection? i just get nothing displayed and it doesn't loop.

A: (SalimFadhley?) This is actually my normal way of using Smarty - smarty does not care where the data is assigned from as long as it gets it's data. A common point of confusion when making objects work together is the distinction between passing by value and by reference.[This is only true in PHP 4. PHP 5 always passes objects by reference. In PHP 5 the object must be cloned to pass it by value.] Have a look at this code example:

<?php

define('HHUB_DIR', dirname(__FILE__));

define('TEMPLATE_DIR', HHUB_DIR.'/templates/');

require_once("inc/adodb/adodb.inc.php");

require_once("smarty/Smarty.class.php");

require_once("inc/Page.inc.php");

require_once("inc/connections.inc.php");

$smarty = new Smarty;

$page = new PageObject?? ( $_GET["type"] , $_GET["id"] , $connection["content"], $_GET["eid"]);

$page->get_page();

$page->output( &$smarty);

$smarty->debugging = true;

$smarty->display(TEMPLATE_DIR.'holmesplace.html');

?>

This is actually the source code of the page-generator for my [Holmes Place] (link not valid when last checked) project. You can see that having created a smarty object (called $smarty), and an object that works out what data to fetch ($page), I pass the smarty object by reference into $page's 'output' method. Did you spot the & symbol before the $smarty. This tells PHP that I want it to pass a reference to the original $smarty object rather than a copy of $smarty (PHP's default).

If you dont pass by reference (Then you are passing by value), PHP takes a copy of the $smarty object before feeding it into the $output method. Any changes to the object are completely lost when the method ends. On the other hand if you do pass by reference, PHP does not bother to copy the object - your method works on the the one and only $smarty object. When the method ends the $smarty object will continue to exist and any changes that have been made to it will have been

Passing by reference is usually a lot quicker than passing by value (especially with big objects), for the simple reason that PHP does not have to copy and re-allocate memory each time you use an object as an argument to a function.

Q: I have some content in the memory I want to use as smarty template. Must I create a file from it?

A: (Josh Johnson) http://smarty.php.net/manual/en/templates.from.elsewhere.php

Q: I can't seem to get the template_exists function to work correctly, what might be the correct syntax for it?

A: http://smarty.php.net/manual/en/api.template.exists.php

It takes exactly the same syntax as the fetch() and display() functions.

if ($smarty->template_exists("path/to/my/template.tpl")) {

$smarty->display("path/to/my/template.tpl");
}

As the documentation says you can also use custom resource locators for addressing your template.

If it doesn't work correctly you can also try to locate the template using the "file:" resource locator and an absolute path to your template:

if ($smarty->template_exists("file:/absolute/path/to/my/template.tpl") {

$smarty->display("file:/absolute/path/to/my/template.tpl");
}

Q: Can I force Smarty to store compiled templates into database rather than file on the disk?

A: Not yet... But perhaps you could find someone to implement it ;)

A: You shouldn't, it will be a great performance disadvantage, because PHP cannot execute them directly from database.

A: Technically, you can use PHP's recently added streams API to implement your storage type at the PHP level. This would enable PHP to include your code just as if it was a local file; unfortunately, this isn't trivial to implement and would likely require some customizations to Smarty as well.

A: Ugly hack, but I guess it works for sending the compiled code to a string:

function compile_to_string(&$smarty, $filename) {

$_params = array('resource_name' => $filename);

$smarty->_fetch_resource_info($_params);

$smarty->_compile_source($filename, $_params['source_content'], $compiled_content);

return($compiled_content);
}

Q: Is there anyway to send the compiled template code to a variable instead of $smarty->display() that output's it ? (I want to create a template for mail e.g)

A: use $smarty->fetch($name_of_template_file)-

A: use $smarty->fetch("template.tpl", $assign_template_to_this)

A: I couldn't get the previous answer to work (but I'm no expert), I got this to work though

$assign_template_to_this = $smarty->fetch("template.tpl");

Q: How should I ask Smarty to display a page incrementally i.e. one that takes a long time to generate?

A1: bram_van_leur Once Smarty compiled your template into a PHP file it's just handled as a PHP-file. So it easily runs from top to bottom and if you don't use to much output-buffering PHP will flush it's buffer once in a while and send already rendered parts to the browser

A2: note that you are really trying to override the browser's output buffering and some of PHP's. you can force PHP to flush its buffer with flush(); you can force IE to flush (sometimes) by putting things in tables and then closing the tables. but sometimes you just have to wait on the browser.

Q: Is there an instruction to get all vars assigned to a template? (Mattia)

A: Yes, using get_template_vars (Oscar Fernandez Sierra):

// get all assigned template vars

$tpl_vars = $smarty->get_template_vars();

// take a look at them

var_dump($tpl_vars);

A: I would love to know if there is a better way than the stuff below. (Ed Pascoe)

I find that I often need to extract a single field from an array that has been assigned in smarty, Eg. Say a database row called domain with a field called clientName. Smarty would see it as "{$domain.clientName}", but the stuff from get_template_vars requires a completly different syntax. I usually extend the Smarty class to add in the function below, so the code would look something like:

class MailTemplate? extends Smarty{

function val($var){

$data="";

foreach(explode('.',$var) as $v){

if (empty($data)) $data=$this->get_template_vars($v);

else $data=$data[$v];

}

return $data;

}
}

$mt= new MailTemplate?;

.......

print $mt->val("domain.clientName");

Q: Is there a way to use ONE template directory for a site with multiple directories?

A: The easiest way to use one single template directory is to specify it in the Smarty.class.php file (the main smarty engine file). Specifically:

/**

* The name of the directory where templates are located.

*

* @var string

*/

var $template_dir = '/path/to/your/templates';

In this way, you specify an absolute path to the template folder on your server, and all templates will live in it. You can also specify a particular value for the template_dir variable at runtime:

http://smarty.php.net/manual/en/api.variables.php#variable.template.dir

===

Be aware that you should probably similarly specify an absolute path for your $compile_dir - or else it will default to "a templates_c dir underneath the current directory".

===

An additional caveat to be aware of (that I have experienced) certainly whilst using a single $compile_dir - template output overwriting. If you have two templates called e.g. footer.tpl, then the compiled output can end up being overwritten as people request each of those templates whilst browsing your site. A workaround is simply to avoid using templates with the same names. e.g. footer_main.tpl and footer_special.tpl.

Q: Is there a way designers can view all assigned vars?

(zer0fill) Yes, tell the designer to add {debug} in the template. the popup window will have all the assigned vars

(thanks boots)

Q: Is there a way programmers can access all vars in a template file through PHP?

It would be very useful do be able to do something like this to test a template:

$vars = get_vars_from_template('index.tpl');

foreach ($vars as $v){

$smarty->assign($v, $v." GOES HERE");
}

But what do we do when we encounter arrays, objects, etc..

A #1: Like this:

preg_match_all('/{\$(.*?)}/',implode('',file('templates/index.tpl')),$vars,2);

foreach ($vars as $v){

echo $v[1]."<br>";
}

Q: How come the date_format modifier doesn't work right?

date_format uses the strftime() function of PHP.

Quoted from the PHP manual for strftime():

Note: Not all conversion specifiers may be supported by your C library, in which case they will not be supported by PHP's strftime(). Additionally, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch. This means that e.g. %e, %T, %R and %D (there might be more) and dates prior to Jan 1, 1970 will not work on Windows, some Linux distributions, and a few other operating systems. For Windows systems a complete overview of supported conversion specifiers can be found at this MSDN website:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_strftime.2c_.wcsftime.asp

Q: Is there anything I should know about using Smarty with my custom error handler?

Does Smarty implement it's own handler, or change the reporting level? Any other pitfalls that might bypass a custom handler? Can you guess that I'm having a few problems with this... :) -- HappyDog?? (30th August 2005)

IDE

Q: How do I configure Dreamweaver to recognize Smarty template (.tpl) files?

A #1: ConfiguringDreamweaver

A #2: (svenax) Don't. Name the files Name.tpl.html instead.

A #3: Go with #1 .. making them .html doesn't account for {functions}....

A #4: In DW04 go to -> "Edit" -> "Preferences" -> "Filetypes/Editors" -> "Open in Codeview" ADD ".tpl"

Q: Is there a Smarty edit mode for jEdit?

A: There seems to be one included in jEdit 4.2.

A: I don't believe that a smarty edit mode is in jEdit 4.2 by default. However, you can easily [download] and install the config. for a smarty mode. To install, simply place the xml file in your jEdit/modes/ folder. From then on, you will see Smarty syntax-highlighting whenever you open a *.tpl file. You will need to restart jEdit in order for the new settings to take effect.

Other questions

Q: Can I create a proprietary software, and sell it with Smarty?

A: Yes, you can. Smarty is licensed under the [LGPL] and distributing an unmodified smarty source as part of a commercial product is just fine. Be sure it contains all the LGPL license files, copyright notices, etc. Also anywhere you mention copyrights on your own source code, you should also mention copyrights of third party software such as Smarty.

A: As far as I know the GPL licence doesn't allow any work using a GPL software in any way different by mere aggregation to be released with a licence different from GPL. For this reason LGPL licence was created. LGPL allows programs using or linking to a library to be released with a different licence.

A: The LGPL is rather liberal but you must absolutely, positively adhere to the few conditions that it implies. Please see the forum, your copy of the LGPL bundled with Smarty and the Free Software Foundation for more specific details. If you fail to do so, then the LGPL specifies that you have NO license to use the software. If in doubt, ask and if you are producing a commercial application, you are encouraged to seek qualified legal advice.

Q: Is there a tutorial on how to create XML using Smarty?

A: Although I have not seen a tutorial explicity showing XML creation with Smarty, Smarty has no such difficulty with this. Smarty will parse any template, whatever the content, and display it accordingly. Displaying the XML will depend on your requirements.

For example if you want the content of your XML displayable to all browsers, you may want to transform it to HTML on the server using XSL. In this case you would use $smarty->fetch() method insted of $smarty->display() to put the XML into a variable for you to manipulate.

Q: How do I assign function results?

I have a registered function returning an array and I can't figure out how to use the

results of the array in a template. I.e. I want to use individual values from the array

at various points in the template, not just display the whole array.

A: Use it exactly like any other assigned array either using {section} or {foreach} tags

{fooReturnArray assign="bar"}

{section loop=$bar name="i"}

{$bar[i]}

{/section}

A2: If the function returns the result in an anonymous variable you can 'capture' it first:

{capture name="returned_array"}

{myfunction ident="some_parameter"}

{/capture}

{assign var="bar" value=$smarty.capture.returned_arry}

{section loop=$bar name="i"}

{$bar[i]}

{/section}

Q: What is this Gold Star thing all about? I found a Gold Star on my Entry??

A: If you happen to wind up with a GoldStar?? on your Wiki items, it is probably

because someone found your material really helpful?

Q: Why is it called Smarty? Who came up with such a name?

A: Monte Ohrt named the template engine Smarty. It was originally conceived as a "smart" template engine, doing much more than basic tag replacement. Smarty also had a predecessor, an in-house template engine named "SmartTemplate??" written by Andrei Zmievski.

Q: Why isn't capitalize working properly with special chars, such as the swedish ?

A: Depending on your webhosts configuration you might experience weird behavior when using capitalize. Utfrsljning will be converted into UtfRsLjning??. This is because the perl_regex being used is set to break up "per word" (\d) (a-z, 0-9). To solve this you can change plugins/modifier.capitalize.php (line ~23 I think) from:

return preg_replace_callback('!\b\w+\b!', 'smarty_modifier_capitalize_ucfirst', $string);

to

return preg_replace_callback('!\b\[a-z0-9]+\b!', 'smarty_modifier_capitalize_ucfirst', $string);

(For those of you who sees ?????? it says the html-characters &aring;&auml;&ouml;&Aring;&Auml;&Ouml; but using native chars). Surely this is not the ultimate solution, but the 'hack' works...

A2: If you use other characters than then you replace the line above with this one instead:

return preg_replace_callback('!\b\[a-z0-9\200-\377]+\b!', 'smarty_modifier_capitalize_ucfirst', $string);

This code will threat a-z and all "extended" characters as letters. Unfortunately it will treat some special characters (like (copyright) and (degrees)) as letters too...

A3: Depending on the specific problem, it might be better to use CSS for case modification:

  h1 { text-transform: uppercase }