December 9, 2005

Smarty templating and presentation library for PHP

Author: Eddie Tejeda

PHP has historically been a simple scripting language used for quickly developing small web sites with dynamic content. But newer features have given the language the structure and libraries for building larger applications. One such library is Smarty, a templating and presentation engine. Smarty helps developers build applications in modules by separating the presentation layer from the application code. This article covers some of the basic features of Smarty for developers.

Smarty provides the framework for creating a distinct layer for the user interface. A distinct interface layer gives designers the flexibility to modify or redo the interface without altering any of the application code. The template code looks just like HTML and allows designers to work in a familiar environment. Designers need only learn a few simple commands that retrieve the data from PHP. They do not need to know how or where the data comes from or how it got there. The same goes for the application code; changing the logic or the way the application gets data does not affect the presentation layer. Having this strict separation of code and presentation can sometimes be cumbersome, but results in code that is easier to maintain.

To use Smarty, download the latest version and read the documentation. The installation process is easy and involves moving Smarty into a location that PHP can access and creating a few directories for Smarty to hold templates and temporary files. To manage the initialization process use this class:

<?php
define(SMARTY_INSTALL_PATH, "/path/to/Smarty-2.6.9/");

$current_include_path = ini_get("include_path");
ini_set($include_path.":".SMARTY_INSTALL_PATH);

require_once('Smarty.class.php');

class SmartyManager {

  function &smartyInitialize($path) {
     //detect if the proper directories exist
     if(!is_dir( $path."/templates/") )
	die("SmartyManager::smartyInitialize Error: create templates directory");
     if(!is_dir( $path."/templates_c/") )
	die("SmartyManager::smartyInitialize Error: create template_c directory");
     if(!is_dir( $path."/cache/") )
	die("SmartyManager::smartyInitialize Error: create cache directory");
     if(!is_dir( $path."/config/") )
	die("SmartyManager::smartyInitialize Error: create config directory");

     if(!is_writeable( $path."/templates_c/") )
	die("SmartyManager::smartyInitialize Error: templates_c needs to writable");

     $smarty = new Smarty();
     $smarty->template_dir = $path."/templates/";
     $smarty->compile_dir = $path."/templates_c/";
     $smarty->cache_dir = $path."/cache/";
     $smarty->config_dir = $path."/config/";
     return $smarty;
  }
}
?>

This class detects whether the installation process is complete and then initializes a Smarty object. To use the SmartyManager class, specify the path in SMARTY_INSTALL_PATH in SmartyManager and include it in your application. Next, instantiate a SmartyManager object and pass it the directory where you want to hold your templates and temporary files. The directory you pass it to must have four subdirectories: config, templates, templates_c (which holds compiled templates -- that is, ones which have already merged the application data with the presentation), and cache. When you create a template make sure it goes inside the templates directory.

Here is an example that uses SmartyManager:

<?php
require_once('SmartyManager.class.php'); //include the SmartyManager.class
$manager = SmartyManager(); //create an object;
/* get smarty object from SmartyManager */
$smarty = $manager->smartyInitialize("/var/www/application/presentation");

/* now we are using smarty */
$smarty->assign("items", $items);
$smarty->display('Users.tpl');
?>

After you initialize Smarty you can pass variables for the designer using the assign() method in PHP. The first argument is the name variable used in Smarty and the second will be the value, as shown in the example above. You can assign as many variables as you need. Calling the display() method with the name of the template, Users.tpl in this case, will handle the display. Don't worry about giving a full path to the template -- Smarty always looks at files relative to the templates directory.

Looping though arrays

Now that you have Smarty running, it's time to start creating pages with dynamic data. In most cases, the data structure passed down to Smarty will be arrays, especially associative arrays, because most data will probably come from a database, which are already organized in rows and columns. Here is an example of a 2D array created in PHP:

<php
// filename: users.php
$items = array( 1 => array("first_name" => "eddie","last_name" => "smith" ),
                2 => array("first_name" => "jane","last_name" => "doe" ),
                3 => array("first_name" => "gregory","last_name" => "adams" ));
?>

When you send a 2D array to a Smarty template, you can iterate through the items using a foreach loop. Smarty comes with a few other built-in functions, but here we will only focus on the most common ones. In the template, to get values from an associative array, use dot syntax, similar to the way you access public properties of an object. While foreach provides an easy way to iterate through an array, using the method section provides a bit more control when iterating through the array. The following examples demonstrate a template looping through an array using foreach and then section. (Note: Everything inside {* *} delimiters is a comment.):

{* filename: users.tpl *}
<table>

{if $printUser == "true"}
  {foreach from=$items key=key item=item}
    <tr style="background-color:{cycle values="#EEEEEE, #FFFFFF"}">
      <td>{$item.first_name}</td>
      <td>{$item.last_name}</td>
    </tr>
  {/foreach}
{else}
  <tr><td>We're Not Printing Users Today</td></tr>
{/if}

</table>

In this example, you'll notice that the if and else statements are enclosed in braces, as all Smarty functions (even control functions) are called. The if statement also encloses all of the else statements, and the condition is not closed until the if statement is closed.

Some variable names have a dollar sign, while others do not, and some are enclosed in curly brackets. Variable names that use a dollar sign prefix, as in PHP, already have data in them and can be passed to other functions. If any variable is enclosed in braces and has the dollar sign then it will be printed to the screen no matter what type of quoting surrounds it. Finally, variables that do not have a dollar sign or braces are used when assigning a value to it within a function, but to retrieve their values the previous rules apply.

The actual foreach code is very similar to the foreach code in PHP. The foreach function takes three possible parameters: from is the array you want to iterate through, key is the current position in the array, and item holds the current item.

{* filename: users.tpl *}
{* in this example we print all the values in the array *}
<table>
{section name=user_id loop=$users start=2 step=2 }
  {$users[user_id].first_name}</td>
  {$users[user_id].last_name}</td>
{/section}
</table>

In this example you can see how section works a bit different from foreach. You have a few more options not available in foreach, such as start and step, which tell the loop to begin execution in a specific point in the array, and step specifies how to count through the array. Giving step a negative number causes the loop to count backwards. For a complete list of all the parameters section can take, look at the Smarty documentation.

Variable modifiers

Variable modifiers provide a final opportunity for designers to edit the data before it gets printed to the screen. The syntax is simple, though a bit different from many common programming languages. The function to modify the variable is called directly from the braces enclosing the variable. This is similar to Unix piping (|), which directs the output to a function which will then display. This example demonstrates how to use modifiers:

{* Modifiers1.tpl *}
{* Note: the dots in the end are not done by the function;
 they were added to shorten example *}
{* $paragraph is "The horse raced past the barn fell.\n\nThis sentence is false." *}

{$paragraph|capitalize} {* result: THE HORSE RACED PAST... *}
{$paragraph|count_words} {* result: 11 *}
{$paragraph|count_sentences} {* result: 2 *}
{$paragraph|count_paragraphs} {* result: 2 *}

A list of all modifiers can be found in the variable modifiers section of the Smarty site. None of the functions above take any arguments, but passing arguments to modifiers is simple. If a modifier takes arguments, the arguments are passed with a colon-separated list, as in the following example:

{* Modifiers2.tpl *}
{$paragraph|indent:10}
{* the result would be indented 10 spaces *}
{$paragraph|replace:"Wasn't":"Was"}
{* this modifier replaces all occurrences of the first string with the second *}
{$paragraph|count_characters:true}
{* if the argument is true then the result counts spaces, otherwise it doesn't *}

If you perform any of these functions to an array, then all the values of that array will be modified respectively.

Passing objects to Smarty

In order for Smarty to use objects created by PHP, you first need to instantiate an object in PHP and pass to Smarty using the register_object() method. You access an object in a template similar to the way you call Smarty's built-in functions. Here's an example of how to pass an object to Smarty:

<?php
// this is the example class
class Classname {
    function methodname($name) {
        return "$name";
    }
}
//we create an object
$obj = new Classname;
// registering the object by reference
$smarty->register_object("obj",$obj);
$smarty->display("index.tpl");
?>

The following is an example of a template accessing the methods of an object. The code passes parameters to the function, and will store the result in a variable if assign is defined with a name of a variable.

{* template of an object calling a method *}
{foobar->methodname p1="eddie" assign="output"}
the name is {$output}

That covers most of the basics of Smarty. Smarty's features, such as letting you build your own functions and modifiers, make it a useful tool for building large applications.

Category:

  • PHP
Click Here!