16 Very Useful Smarty Scripting Tips and Techniques to Make Templates Smarter

Posted: 26 March, 2009 in Programming

A compilation of useful Smarty template scripting tips and techniques to help build smarter dynamic templates for PHP programmers and template designers. Great practical resource for people who are learning to script Smarty templates. Saves valuable time on research.

  1. HTML Code Reuse

    Use {capture} tags to assign any output it generates into a variable that you can use to display the captured content multiple times throughout your templates.

    Assign the output to the variable “nav”:

    {capture name='nav'}
    <ul>
    {section name=item loop=$nav}
      <li><a href="{$nav[item].url}" title="{$nav[item].title}">{$nav[item].label}</a></li>
    {/section}
    </ul>
    {/capture}

    Show the captured content.

    {$smarty.capture.nav}

    You can also assign the output to a template variable.

    {capture name='nav' assign='navmenu'}

    Then display the content using the variable.

    {$navmenu}

    When name is not specified, “default” is used and can be displayed like this:

    {$smarty.capture.default}
  2. Passing Variables from Sub-Templates

    While using $GLOBALS array via {php} would do the trick, using {capture} is neat and recommended considering most template designers don’t want to get their hands dirty on PHP. After all, smarty template files are not meant for PHP codes.

    In header.tpl:

    {capture name='columns'}3{/capture}

    Then, in index.tpl:

    {include file='header.tpl'}
    {if $smarty.capture.columns == '3'}
    . . .
    {/if}
    {include file='footer.tpl'}

    Can even access the variable inside footer.tpl:

    {if $smarty.capture.columns == '3'}
    . . .
    {/if}
  3. Including Sub-Templates using Custom Delimiters

    To include a sub-template that inserts values of template variables in embedded JavaScript or CSS rules, use {php} tags, instantiate a new Smarty object, assign values to template variables, and finally, display the sub-template.

    main.tpl

    {php}
    $smarty = new Smarty;
    $smarty->left_delimiter = '<!--{';
    $smarty->right_delimiter = '}-->';
    $smarty->assign('size', '36px');
    $smarty->assign('pre', 'Great');
    $smarty->assign('post', 'Templates');
    $smarty->display(message.tpl');
    {/php}

    message.tpl

    <style type="text/css">
    <!--
    h2 {font-size: <!--{$size}-->}
    -->
    </style>
    <h2>Welcome to the World of <!--{$pre|capitalize}--> Smarty  <!--{$post|capitalize}--></h2>
    <script language="javascript" type="text/javascript" >
    <!--
    function welcome(){
      alert('Welcome to the World of <!--{$pre|capitalize}--> Smarty  <!--{$post|capitalize}-->');
    }
    welcome();
    -->
    </script>

    Above code will display “Welcome to the World of Great Smarty Templates” with font size 36px and pops up an alert with same message.

  4. Debugging Smarty Templates

    Smarty has a debugging console that allows you to easily examine assigned template variables, included templates and config file variables for the current template.

    To enable the debugging console:

    1. Set Smarty $debugging property to true.

      <?php
      $smarty = new Smarty;
      $smarty->debugging = true;
      ...
      ?>
    2. If the debug console window does not pop up when you load the page, set $debug_tpl property to the path of your debug template. By default, Smarty will look for the “debug.tpl” in SMARTY_DIR. This file is included in Smarty distributions and can be found in library “libs/” folder.

    The easiest and quickest way to enable debugging console is by placing a {debug} tag in your templates. It works regardless of the $debugging settings in the php script. However, it only allows you to see all the available variables within the scope of the current template.

    Example usage:

    <h1>{$title}</h1>
    {debug}
    <p>{$description}</p>
  5. Accessing Request Variables from Smarty Templates

    Request variables available in PHP scripts can be accessed from your Smarty templates through the reserved template variable {$smarty}. Request variables include $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, and $_SESSION.

    Examples:

    Output the value of $_GET[‘page’] from the url “http://www.jampmark.com/index.php?page=about&#8221;

    {$smarty.get.page}

    Output the value of $_POST[‘page’] from a posted form

    {$smarty.post.page}

    Output a cookie variable, $_COOKIE[‘status’] from request header

    {$smarty.cookies.status}

    Output a server variable, $_SERVER[‘SERVER_NAME’]

    {$smarty.server.SERVER_NAME}

    Output a system environment variable, $_ENV[‘PATH’]

    {$smarty.env.PATH}

    Output a session variable, $_SESSION[‘id’]

    {$smarty.session.id}

    Output the value of “username” from merged get/post/cookies/server/env

    {$smarty.request.username}
  6. Accessing Template Variables from PHP script

    You can access template variables using Smarty method get_template_vars() in PHP scripts. However, template variables are only available after or during template execution. The latter can be achieved by embedding PHP code directly into the smarty template using {php} tags or by including a php file using the built-in function {include_php} tag.

    Consider the template code:

    {assign var='title' value='Smarty Templates'}

    Accessing variables after template execution:

    // execute the template and return the result to a variable
    $page = $smarty->fetch('index.tpl');
    
    // will output "Smarty Templates"
    echo $smarty->get_template_vars('title');
    
    // assign value to the variable
    $smarty->assign('title', 'The Great Smarty Templates');
    
    // this will output "The Great Smarty Templates"
    echo $smarty->get_template_vars('title');
    
    // this will dump all variables assigned in the template
    var_dump($smarty->get_template_vars());

    There are two (2) ways to access variables during template execution from inside {php} tags.

    {php}
    // using $this->_tpl_vars
    echo $this->_tpl_vars['title'];
    
    // using $this->get_template_vars() method
    // the variable $this, is a smarty object
    echo $this->get_template_vars('title');
    {/php}
  7. Variable Substitution in String with Double Quotes

    This works similar to that of PHP where variables embedded in a double quoted string are expanded to their values.

    • Simple substitution:

      With $filename having a value of “footer”, the file attribute below will have a value of “templates/footer.tpl”.

      {include file="templates/$filename.tpl"}

      Code below won’t work because string is surrounded by single quotes.

      {include file='templates/$filename.tpl'}
    • Array indexes

      Assuming $module[1] contains “user_menu”:

      The $module[1] below will be replaced with “user_menu” and will translate into “user_menu.tpl”.

      {include file="$module[1].tpl"}

      With $index value equal to 1, code below will do the same thing as above. In this case, enclose with backticks.

      {include file="`$module[$index]`.tpl"}
    • Associative Arrays

      Let’s put $item[‘name’] equals “”Computer”:

      The variable $item.name below will be replaced with “Computer” so value will be “Computer unit”.

      {assign var=’label’ value="`$item.name` unit"}

      With $prop value equals to “name”, the following is equivalent to the above.

      {assign var='label' value="`$item.$prop` unit"}
    • Objects

      Say, we have an object variable where $book->title contains “Smarty Templates”.

      The $book->title below will be replaced with “Smarty Templates” so $msg will have value of “My Smarty Templates book”.

      {assign var='msg' value="My `$book->title` book"}

      With $property equal to “title”, $msg will have same value as above.

      {assign var='name' value="`$book->$property`"}

      Note: Always enclose variable names with backticks (`) when they contain dots (.), object references (->), or when using index variables for arrays.

  8. Handling Blank Template Variables

    Blank template variables may break your HTML table layout. It may also cause <img> tags to load your web page in the background and generate multiple entries in the access log for every single visit due to src attribute being empty.

    Use {if} tag to output a default value when a variable is empty. Or use the shortcut, the “default” variable modifier.

    Consider the following code that outputs &nbsp; inside HTML table cell:

    <table><tr><td>
    {if $user eq ''}
      &nbsp;
    {else}
      {$user}
    {/if}
    </td></tr></table>

    The shortcut:

    <table><tr><td>{$user|default:'&nbsp;'}</td></tr></table>

    Here is a code that handles <img> src properly:

    <img src="{if $image_url eq ''}/images/default.png{else}{$image_url}{/if}" />

    Or simply:

    <img src="{$image_url|default:'/images/default.png'}" />

    The shortcut makes a cleaner code but using it throughout your templates can be a bit ugly.

    Consider the code below:

    <a href="{$image_url|default:'/images/default.png'}">
    <img src="{$image_url|default:'/images/default.png'}" />
    </a>
    <p>Path: {$image_url|default:'/images/default.png'}</p>

    Here is a much cleaner version using {assign} tag with  default .

    {assign var='image_url' value=$image_url|default:'/images/default.png'}
    <a href="{$image_url}">
    <img src="{$image_url}" />
    </a>
    <p>Path: {$image_url}</p>
  9. Passing Variables to Sub-Templates

    It is common for web developers and web designers to place repetitive contents into separate template files and {include} them where needed. One typical example is header.tpl which includes the html title tag. Suppose need it to show different page titles depending on which page included it. You can do that by placing “title” as attribute of {include} tag and this is how we pass parameters to sub-templates in Smarty

    Example template code that includes header.tpl with parameter “title”.

    {include file='header.tpl' title='Welcome!'}
    {include file='footer.tpl'}

    In header.tpl

    <html>
    <head>
    <title>{$title|default:'Smarty World'}</title>
    </head>
    <body>

    In footer.tpl

    </body>
    </html>
  10. Formatting Numeric Outputs

    You don’t need to assign multiple variables with same values in different formats because there is a variable modifier in Smarty that allows you to format output. “string_format” uses same formatting syntax in sprintf() function in PHP.

    Example:

    {$number}
    {$number|string_format:’%.2f’}
    {$number|string_format:’%d’}

    With $number equal to 23.5787446, the code above will output:

    23.5787446
    23.58
    24
  11. Handling Dates

    As a rule of thumb, PHP coders should always pass dates to Smarty templates as timestamps. This allows template designers to use the “date_format” modifier for full control over date formatting. You also make it easy to compare dates if necessary.

    Default date format:

    {$createDate|date_format}

    Will output:

    Feb 28, 2009

    Custom date format:

    {$createDate|date_format:'%Y/%m/%d'}

    Will output:

    2009/02/28

    Comparing dates:

    {if $startDate < $endDate}
      . . . do something . .
    {/if}

    To convert {html_select_date} output into timestamp format in PHP, use the function below:

    <?php
    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);
    }
    ?>
  12. Obfuscating E-mail Addresses

    When showing e-mail addresses on your web pages, make sure they are obfuscated to somehow hide them from spam bots. In Smarty, you can use {mailto} tag to obfuscate an e-mail address. It works by scrambling the e-mail address using Javascript and embeds it in the HTML source. The e-mail address will still be readable by humans while giving spamming bots hard time to read.

    Example:

    <div id="contact">Contact us at
    {mailto address=$emailAddress encode='javascript' subject='Hi Smarty'}
    </div>
  13. Alternating CSS Styles

    Displaying rows of information in alternating background colors is a great way to improve readability. In Smarty, you can use the {cycle} tag to set alternating CSS styles.

    Here is a sample code that sets “odd” or “even” css class to tags in alternates.

    <table>
    {section name=item loop=$items}
      <tr class="{cycle values='odd,even'}">
        <td>{$items[item].title}</td>
        <td>{$items[item].description}</td>
      </tr>
    {/section}
    </table>

    Then set CSS “background-color” property with different colors for each CSS class.

  14. Fetch and Display Contents on Demand

    Traditionally, inserting new components into your templates would require adding data collection logic to the PHP script. On the reverse, removing components from your templates would also require removal of data collection logic from PHP script to optimize its performance.

    This can be a maintenance nightmare for large and complex projects especially when PHP programmer and template designer are two different people.

    The solution is to write component functions that are executed on demand when triggered by the template.

    There are 2 ways to write on demand scripts:

    1. Use the {insert} tag

      It works by calling a user-defined php function that begins with “insert_” and inserts the return value on the template where the {insert} tag was placed. The tag is useful for displaying dynamic contents because its output is never cached regardless of the template cache settings.

      The PHP code:

      <?php
      require 'Smarty.class.php';
      $smarty = new Smarty;
      $smarty->display('index.tpl');
      
      function insert_getNews($params)
      {
        if ($params['type'] == 'latest') {
          // retrieve news items and process
        }
        // return the result
        return $html;
      }
      ?>

      The template code in “index.tpl”:

      <div class="news">
      <h3>Latest Smarty News</h3>
      {insert name='getNews' type='latest'}
      </div>
    2. Write your components as plugins

      Plugin is a module in its own file that contains PHP script for fetching necessary data and assigns them to template variables. It is always loaded on demand that you don’t have to worry about adding and removing lines of logic from your PHP scripts.

      As an example, here is a simple Smarty news plugin.

      function.news.php – observe naming convention and put in plugins directory usually “smarty/libs/plugins” otherwise set the $plugins_dir.

      <?php
      // function for fetching news items
      function fetch_news($symbol)
      {
        // the news items could be queried from a database
        // but for this example we just create and return an array of items.
        $items = array(
        array('title'=>'Smarty News', 'description'=>'Great Smarty Templates'),
        array('title'=>'PHP News', 'description'=>'Smarty Templating Engine'),
        );
        return $items;
      }
      
      function smarty_function_news($params, &$smarty)
      {
        // call our custom function
        $news = fetch_news($params['symbol']);
      
        // assign template variable
        $smarty->assign($params['assign'], $news);
      }

      To use Smarty news in your index.tpl for display,

      {news symbol='SMARTY' assign='items'}
      <ul>
      {section name=item loop=$items}
        <li><h3>{$items[item].title}</h3><p>{$items[item].description}</p></li>
      {/section}
      </ul>
  15. Using CSS and Javascript Codes in a Smarty Template

    By default, Smarty parses anything that is inside { and } characters including those used in CSS rules and Javascript functions. Without proper coding and escaping techniques, your page will render into a disaster.

    There are four (4) ways to escape from Smarty parsing:

    1. Separate your CSS and Javascript codes into their own files and include them into your template using standard HTML methods.

      Linking a CSS file:

      <LINK REL=STYLESHEET HREF="style.css" TYPE="text/css">

      Including a Javascript file:

      <script type="text/javascript" src="popup.js"></script>
    2. Enclose embedded CSS and Javascript code with {literal} and {/literal} tags so Smarty engine would leave them alone.

      Embedding CSS:

      <style type="text/css">
      <!--
      {literal}
      p {text-indent: 10pt}
      body {margin:0; padding:0;}
      {/literal}
      -->
      </style>

      Declaring embedded Javascript function:

      <script language="javascript" type="text/javascript" >
      <!--
      {literal}
      function hello_world(){
        alert('Hello Smarty World');
      }
      {/literal}
      -->
      </script>
    3. Change Smarty’s $left_delimiter and $right_delimiter to custom delimiter strings so you can use curly braces in your templates. In addition, it would allow you to insert template variable values into your CSS and Javascript codes to make them dynamic on the fly at server side.

      The PHP code:

      <?php
      require 'Smarty.class.php';
      
      $smarty = new Smarty;
      
      $smarty->left_delimiter = '<!--{';
      $smarty->right_delimiter = '}-->';
      
      $smarty->assign('title', 'The Smarty Template Engine');
      $smarty->assign('element', 'h1');
      $smarty->assign('size', '36px');
      $smarty->assign('popup', 'alert');
      $smarty->display('index.tpl');
      ?>

      The Smarty Template “index.tpl”:

      <head>
      <style type=”text/css”>
      <!--
      <!--{$element}--> {font-size: <!--{$size}-->}
      -->
      </head>
      <body>
      <<!--{$element}-->><!--{$title}--></<!--{$element}-->>
      <script language="javascript" type="text/javascript" >
      <!--
      function show_popup()
      {
        <!--{$popup}-->('<!--{$title}-->');
      }
      //-->
      </script>
      </body>

      The code above will output:

      <head>
      <style type="text/css">
      <!--
      h1 {font-size: 36px}
      -->
      </head>
      <body>
      <h1>The Smarty Template Engine</h1>
      <script language="javascript" type="text/javascript" >
      <!--
      function show_popup()
      {
        alert('The Smarty Template Engine');
      }
      //-->
      </script>
      </body>
    4. Use {ldelim} and {rdelim} tags in place of { and } in defining your CSS rules and JavaScript functions assuming the default delimiters are set. This is not practical for real-world use and it will break when delimiters are set to other strings.

      Define CSS rules:

      <style type="text/css">
      <!--
      p {ldelim}text-indent: 10pt;{rdelim}
      body {ldelim}margin:0; padding:0;{rdelim}
      -->
      </style>

      Will output:

      <style type="text/css">
      <!--
      p {text-indent: 10pt;}
      body {margin:0; padding:0;}
      -->
      </style>
  16. Caching Smarty Templates

    Caching speeds up calls to display() and fetch() methods by saving its output to a file. This file is then displayed instead of regenerating the output. Use caching if your content does not change very often. Set $caching = 2 and use $cache_lifetime to control how much time you want to keep the cache enough to display fresh changes on your contents.

    Set caching on:

    <?php
    require 'Smarty.class.php';
    $smarty = new Smarty;
    
    // When $caching = 1,
    //   $cache_lifetime = 1 will force the cache to never expire
    //   $cache_lifetime = 0 will cause the cache to always regenerate
    // When $caching = 2,
    //   $cache_lifetime sets the cache expiry which can also be set for individual template.
    $smarty->caching = 2; // lifetime is per cache
    
    // Regenerates cached content if any templates or config files that are part of this cache are changed 
    $smarty->compile_check = true;
    
    // $smarty->force_compile = true; will force the cache to always regenerate
    
    // set the cache_lifetime for index.tpl to 5 minutes
    $smarty->cache_lifetime = 300;
    $smarty->display('index.tpl');
    
    // set the cache_lifetime for home.tpl to 1 hour
    $smarty->cache_lifetime = 3600;
    $smarty->display('home.tpl');
    ?>

    2 things to consider seriously when implementing caching:

    1. It is not recommended to put the cache directory under the web server document root. Set $cache_dir to a directory not accessible from the web.
    2. Make sure the cache directory is writeable by the web server.

There you have it. The 16 Smarty scripting tips and techniques to help you build smarter templates for your Smarty web projects.

For anything else, visit the official web site of Smarty Template Engine for PHP

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s