Appendixes Troubleshooting Smarty/PHP errors Smarty can catch many errors such as missing tag attributes or malformed variable names. If this happens, you will see an error similar to the following: Smarty errors Warning: Smarty: [in index.tpl line 4]: syntax error: unknown tag - '%blah' in /path/to/smarty/Smarty.class.php on line 1041 Fatal error: Smarty: [in index.tpl line 28]: syntax error: missing section name in /path/to/smarty/Smarty.class.php on line 1041 Smarty shows you the template name, the line number and the error. After that, the error consists of the actual line number in the Smarty class that the error occured. There are certain errors that Smarty cannot catch, such as missing close tags. These types of errors usually end up in PHP compile-time parsing errors. PHP parsing errors Parse error: parse error in /path/to/smarty/templates_c/index.tpl.php on line 75 When you encounter a PHP parsing error, the error line number will correspond to the compiled PHP script, not the template itself. Usually you can look at the template and spot the syntax error. Here are some common things to look for: missing close tags for {if}{/if} or {section}{/section}, or syntax of logic within an {if} tag. If you can't find the error, you might have to open the compiled PHP file and go to the line number to figure out where the corresponding error is in the template. Tips & Tricks Blank Variable Handling There may be times when you want to print a default value for an empty variable instead of printing nothing, such as printing "&nbsp;" so that table backgrounds work properly. Many would use an {if} statement to handle this, but there is a shorthand way with Smarty, using the default variable modifier. Printing &nbsp; when a variable is empty {* the long way *} {if $title eq ""} &nbsp; {else} {$title} {/if} {* the short way *} {$title|default:"&nbsp;"} Default Variable Handling If a variable is used frequently throughout your templates, applying the default modifier every time it is mentioned can get a bit ugly. You can remedy this by assigning the variable its default value with the assign function. Assigning a template variable its default value {* do this somewhere at the top of your template *} {assign var="title" value=$title|default:"no title"} {* if $title was empty, it now contains the value "no title" when you print it *} {$title} Passing variable title to header template When the majority of your templates use the same headers and footers, it is common to split those out into their own templates and include them. But what if the header needs to have a different title, depending on what page you are coming from? You can pass the title to the header when it is included. Passing the title variable to the header template mainpage.tpl ------------ {include file="header.tpl" title="Main Page"} {* template body goes here *} {include file="footer.tpl"} archives.tpl ------------ {config_load file="archive_page.conf"} {include file="header.tpl" title=#archivePageTitle#} {* template body goes here *} {include file="footer.tpl"} header.tpl ---------- <HTML> <HEAD> <TITLE>{$title|default:"BC News"}</TITLE> </HEAD> <BODY> footer.tpl ---------- </BODY> </HTML> When the main page is drawn, the title of "Main Page" is passed to the header.tpl, and will subsequently be used as the title. When the archives page is drawn, the title will be "Archives". Notice in the archive example, we are using a variable from the archives_page.conf file instead of a hard coded variable. Also notice that "BC News" is printed if the $title variable is not set, using the default variable modifier. Dates As a rule of thumb, always pass dates to Smarty as timestamps. This allows template designers to use date_format for full control over date formatting, and also makes it easy to compare dates if necessary. NOTE: As of Smarty 1.4.0, you can pass dates to Smarty as unix timestamps, mysql timestamps, or any date parsable by strtotime(). using date_format {$startDate|date_format} OUTPUT: Jan 4, 2001 {$startDate|date_format:"%Y/%m/%d"} OUTPUT: 2001/01/04 {if $date1 < $date2} ... {/if} When using {html_select_date} in a template, The programmer will most likely want to convert the output from the form back into timestamp format. Here is a function to help you with that. converting form date elements back to a timestamp // this assumes your form elements are named // startDate_Day, startDate_Month, startDate_Year $startDate = makeTimeStamp($startDate_Year,$startDate_Month,$startDate_Day); function makeTimeStamp($year="",$month="",$day="") { if(empty($year)) $year = strftime("%Y"); if(empty($month)) $month = strftime("%m"); if(empty($day)) $day = strftime("%d"); return mktime(0,0,0,$month,$day,$year); } WAP/WML WAP/WML templates require a php Content-Type header to be passed along with the template. The easist way to do this would be to write a custom function that prints the header. If you are using caching, that won't work so we'll do it using the insert tag (remember insert tags are not cached!) Be sure that there is nothing output to the browser before the template, or else the header may fail. using insert to write a WML Content-Type header // be sure apache is configure for the .wml extensions! // put this function somewhere in your application, or in Smarty.addons.php function insert_header() { // this function expects $content argument extract(func_get_arg(0)); if(empty($content)) return; header($content); return; } // your Smarty template _must_ begin with the insert tag example: {insert name=header content="Content-Type: text/vnd.wap.wml"} <?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <!-- begin new wml deck --> <wml> <!-- begin first card --> <card> <do type="accept"> <go href="#two"/> </do> <p> Welcome to WAP with Smarty! Press OK to continue... </p> </card> <!-- begin second card --> <card id="two"> <p> Pretty easy isn't it? </p> </card> </wml> Componentized Templates This tip is a bit of a hack, but still a neat idea. Use at your own risk. ;-) Traditionally, programming templates into your applications goes as follows: First, you accumulate your variables within your PHP application, (maybe with database queries.) Then, you instantiate your Smarty object, assign the variables and display the template. So lets say for example we have a stock ticker on our template. We would collect the stock data in our application, then assign these variables in the template and display it. Now wouldn't it be nice if you could add this stock ticker to any application by merely including the template, and not worry about fetching the data up front? You can embed PHP into your templates with the {php}{/php} tags. With this, you can setup self contained templates with their own data structures for assigning their own variables. With the logic embedded like this, you can keep the template & logic together. This way no matter where the template source is coming from, it is always together as one component. componentized template {* Smarty *} {php} // setup our function for fetching stock data function fetch_ticker($symbol,&$ticker_name,&$ticker_price) { // put logic here that fetches $ticker_name // and $ticker_price from some resource } // call the function fetch_ticker("YHOO",$ticker_name,$ticker_price); // assign template variables $this->assign("ticker_name",$ticker_name); $this->assign("ticker_price",$ticker_price); {/php} Stock Name: {$ticker_name} Stock Price: {$ticker_price} As of Smarty 1.5.0, there is even a cleaner way. You can include php in your templates with the {include_php ...} tag. This way you can keep your PHP logic separated from the template logic. See the include_php function for more information. componentized template with include_php load_ticker.php --------------- <?php // setup our function for fetching stock data function fetch_ticker($symbol,&$ticker_name,&$ticker_price) { // put logic here that fetches $ticker_name // and $ticker_price from some resource } // call the function fetch_ticker("YHOO",$ticker_name,$ticker_price); // assign template variables $this->assign("ticker_name",$ticker_name); $this->assign("ticker_price",$ticker_price); ?> index.tpl --------- {* Smarty *} {include_php file="load_ticker.php"} Stock Name: {$ticker_name} Stock Price: {$ticker_price} Obfuscating E-mail Addresses Do you ever wonder how your E-mail address gets on so many spam mailing lists? One way spammers collect E-mail addresses is from web pages. To help combat this problem, you can make your E-mail address show up in scrambled javascript in the HTML source, yet it it will look and work correctly in the browser. This is done with the mailto plugin. Example of Obfuscating an E-mail Address index.tpl --------- Send inquiries to {mailto address=$EmailAddress encode="javascript" subject="Hello"} Technical Note This method isn't 100% foolproof. A spammer could conceivably program his e-mail collector to decode these values, but not likely. Resources Smarty's homepage is located at http://smarty.php.net/. You can join the mailing list by sending an e-mail to smarty-general-subscribe@lists.php.net. An archive of the mailing list can be viewed at http://marc.theaimsgroup.com/?l=smarty&r=1&w=2 BUGS Check the BUGS file that comes with the latest distribution of Smarty, or check the website.