Designing Smarty Templates
From ThemesWiki
| Official Page |
| Project Documentation |
| Download |
|
Contents |
[edit] Creating a Template
Are you waiting to see how templates work in real-world problems and how you can design them to solve your daily needs? This tutorial will guide you through real-life problems and their solutions. We will see the basics as well as some interesting templates, but won't look at the code in detail.
Can you imagine scenarios in which Smarty templates would be fruitful? Can you imagine how you can realize your wildest web page designs using Smarty? Not yet? This tutorial will help you to tap the full potential of Smarty. Ready? Let's go...
[edit] Design Concepts, from HTML to TPL
Smarty templates are written in simple HTML, with embedded Smarty tags. Whatever you can do with an HTML page, you can do with templates. Templates are not pure HTML. They may contain logic as well as some very basic elements of a programming language. Hence, designing them needs a little bit more planning and you may need to study the templating system as well. Previously there were some templating engines that worked using the variable substitution process. This used to work but was a slow process and template designers weren't able to achieve full flexibility using it. Smarty is much faster as it compiles your templates into raw PHP code, executes it and returns pure HTML to end users. Smarty TPL (Template Programming Language) makes the job easy for you. All you have to know are its syntax and usage. Don't worry as the learning curve of Smarty is short. Smarty TPL is a feature-rich language that allows you to solve almost every kind of presentation problem.
In pure HTML, there was nothing dynamic and everything was processed on the client's machine. Server-side languages like PHP solved this problem. They increased the interactivity to a higher level and are doing a fine job. Smarty was introduced to further ease the life of designers and developers. Let's look at how a static HTML website differs from PHP and Smarty TPL.
Every Smarty template contains some functions and variables. These functions are pre‑programmed to perform various actions. Using variables, you can talk to your programmers. Programmers usually supply data in PHP variables and you have to process them with Smarty functions and variables. Let's see the following examples.
<html> <body> <table width="80%" border="1" cellspacing="0" cellpadding="2"> <tr> <td width="38%" bgcolor="#CCCCCC" ><strong>Profile of Mortuza</strong></td> <td width="62%"> </td> </tr> <tr> <td><strong>Name : </strong></td> <td>Mortuza Morshed </td> </tr> <tr> <td>Born</td> <td>1980</td> </tr> <tr> <td>Blood Group </td> <td>O (+ve) </td> </tr> <tr> <td>Email</td> <td>mortuzamorshed@somedomain.com</td> </tr> </table> <br> <table width="80%" border="1" cellspacing="0" cellpadding="2"> <tr> <td width="38%" bgcolor="#CCCCCC" ><strong>Profile of Ayesha </strong></td> <td width="62%"> </td> </tr> <tr> <td><strong>Name : </strong></td> <td>Ayesha Siddika</td> </tr> <tr> <td>Born : </td> <td>1979</td> </tr> <tr> <td>Blood Group : </td> <td>B (+ve) </td> </tr> <tr> <td>Email : </td> <td>ayeshasiddika@somedomain.com</td> </tr> </table> </body> </html>
This is a typical example to display two profiles. You were lucky to get only two. If there were hundreds or thousands, you would have to write each of them in static HTML form. Let's see how Smarty simplifies this problem, provided you have all this data stored in a database. Following is a sample Smarty template for this:
profiles.tpl
<body>
{foreach item=student from=$students}
<table width="80%" border="1" cellspacing="0" cellpadding="4">
<tr>
<td width="38%" bgcolor="#CCCCCC">
<strong>Profile of {$student.nick}</strong></td>
<td width="62%"> </td>
</tr>
<tr>
<td>Name : </td>
<td>{$student.name}</td>
</tr>
<tr>
<td>Born</td>
<td>{$student.born}</td>
</tr>
<tr>
<td>Blood Group </td>
<td>{$student.blood_grp}</td>
</tr>
<tr>
<td>Email</td>
<td>{student.email}</td>
</tr>
</table><br/>
{/foreach}
</body>
Note that this is simple HTML code with some embedded Smarty variables. So what do these variables contain and how are they populated? Let's take a look at the following PHP script, which populates and displays variables using the Smarty template engine:
profiles.php
<?
include("libs/smarty.class.php");
$smarty = new Smarty ();
[.. your database connection done here ..]
$result = mysql_query("SELECT nick, name, born, blood_grp, email
FROM students st
LIMIT 10
"); //your sql
$students = array(); //just an empty array
while ($row = mysql_fetch_assoc($result))
{
$students[] = $row; //append the whole $row array in $students
}
$smarty->assign("students",$students); //assign
$smarty->display("profiles.tpl"); //compile and render the output
?>
This PHP script simply fetches data from a table students into an array, appends it to a collection array ($students) and finally assigns it to the Smarty engine. Next, it calls the display() method with the template file name as a parameter. The display() method renders your template with these variables and returns the output to your browser.
Now run this script. What do you see? This is the same output as your static HTML produced. It doesn't matter whether your database has hundreds or thousands or more records. They will all be displayed without a single change in business logic or template code.
Take a look at the template code profiles.tpl, which has some portions highlighted. These are the Smarty functions and variables. Variables are managed by the PHP script written by programmers. A designer's job is to use them where they need to be used.
[edit] Introduction to Smarty Variables
In general, variables are containers that store a chunk of data. Smarty variables are no different but in most cases they are populated using a PHP script. While naming the variables, follow the same convention as you did in PHP. For example, here are some rules:
- Don't start with a numerical character
- Avoid using the name of any reserved variable of PHP (like
$_POSTor$_SERVER) - Give it a meaningful name (for the sake of simplicity)
- Start it with a $ sign
Moreover all Smarty variables must be enclosed with braces {}. These are the basic conventions for naming Smarty variables. Let's see a small template and an example of assigning variables in a script.
sample.tpl
<html>
<body>
Hello {$name}, {$greetings}.
</body>
</html>
Save this file in your templates folder as sample.tpl. In this template, there are two variables named {$name} and {$greetings}. We will now populate these variables using our PHP script.
sample.php
<?php
include("libs/smarty.class.php");
$smarty = new smarty();
$sample_name = "Jamil Ahmed";
$smarty‑>assign("name", $sample_name);
$smarty‑>assign("greetings", "Good Morning");
$smarty‑>display("sample.tpl");
?>
Save this file as sample.php and run it. You will get the following result:
As you can see, Smarty substitutes the template variable {$name} and {$greetings} with data supplied from your PHP script. You can assign variables with the assign() method. In the assign() method, the first parameter is the name of the Smarty variable and the second parameter is the data you want to assign to it. To assign a variable in the template itself, use the assign() function inside your template like this:
{assign var = "date" value = "27th September, 2005"}
Today is {$date}
This will output Today is 27th September, 2005. You don't need to assign any extra data to this {$date} variable. You can assign any data, array and user-defined objects (mainly classes) in a Smarty variable. If you pass an object to your template, you can even access its methods and properties inside your template. Smarty gives you ultimate flexibility while templating. Later in this tutorial we will discuss arrays.
[edit] Starting Templates
In real-world web development, templates can get much more complicated than this. Smarty templates are great for solving complicated development problems in a simple way. If you properly plan before starting your template, it will save your time and money.
Before starting your template, make sure you have a solid understanding of the Smarty foundations. Don't leap in after skim-reading this tutorial! Paying careful and imaginative attention to the Smarty basics will prove worthwhile.
Templates in real life use arrays in a big way. Arrays in Smarty, like those in other programming languages are just a collection of variables. In PHP, arrays are of two different types, one is a non‑associative array where array values have no key, and the other is associative where values are associated with keys. Let's see these two types.
[edit] Non‑associative Array
$students = array("Didar", "Emran", "Hasan", "Deborah", "Shahana");
In the above array example, $students is an array where $students[0] is Didar, $students[1] is Emran and so forth. It is the most common style of populating an array but associative arrays have some benefit over non‑associative arrays.
[edit] Associative Array
$students = array(
"didar" => array("name"=>"Didar Bhuiyan", "roll"=>12)
"emran" => array("name"=>"Emran Hasan", "roll"=>18
"hasan" => array("name"=>"Tanveer Hasan", "roll"=>23));
In this array, all items are pointed to by a key. For example $students["didar"] is an array with two items, name and roll. So if you want to see what is the roll number of Didar then you can access it via $students['didar']['roll']. This code is much more readable than something like $students[0][1]. You should try your best to use associative arrays in your templates for the sake of simplicity. In some complex cases, however, non‑associative arrays are flexible to manage in Smarty templates.
Now that you have some basic idea about arrays, let's see how to pass arrays to Smarty templates and how to manipulate them.
[edit] Passing Arrays to Smarty Templates and Manipulating Them
In this section, we will pass arrays from PHP code to the Smarty templating engine and discuss how to process them. You will find that it is very useful to pass an associative array instead of a non‑associative one because you can access each element of this array with a readable name, which in turn, simplifies the code and also increases the extensibility. Let's take a look at this code:
associative_array.php
<?
include_once("libs/smarty.class.php");
$smarty = new smarty();
$students = array(
"didar" => array("name"=>"Didar Bhuiyan","roll"=>12),
"emran" => array("name"=>"Emran Hasan","roll"=>18),
"hasan" => array("name"=>"Tanveer Hasan","roll"=>23));
$smarty->assign("students",$students);
$smarty->display("associative_array.tpl");
?>
associative_array.tpl
<html>
<body>
<table>
<tr><td>Name</td><td>Roll</td></tr>
{foreach item=student from=$students}
<tr>
<td>{$student.name}</td>
<td>{$student.roll}</td>
</tr>
{/foreach}
</table>
</body>
</html>
Run the associative_array.php file, and you will see output like this:
How is this done for every item in this array? If you look at the code, there is a {foreach} tag, which creates a loop. A loop is a block of code that repeats while a condition is true. Here this loop iterates through every element of the array. When it gets an element, note that it is also an array of a roll and a name item. So we can access them with a dot (.) sign after the array variable. {$student.roll} means the "roll" item of the current array, {$student.name} means the name.
If you pass the array as an object, you can access its elements using OOP-style PHP in your Smarty templates. Let's see how to access them in OOP style.
oop_style.php
<?
include_once("libs/smarty.class.php");
class student
{
var $name;
var $roll;
}
$student = new student();
$student->name = "Arifin";
$student->roll = "29";
$smarty = new smarty();
$smarty->assign("student", $student);
$smarty->display("oop_style.tpl");
?>
oop_style.tpl
<table>
<tr><td>Name</td><td>Roll</td></tr>
<tr>
<td>{$student->name}</td>
<td>{$student->roll}</td>
</tr>
</table>
The only important thing to point out here is the accessing style. Every item is accessed using OOP-style PHP, which means an object followed by an "‑>" operator.
Template designers, note down how the documentation by programmers can help you in these cases. This documentation helps you to create the loop, to access the array and of course to use the appropriate variable in the correct place. Don't neglect the documentation. Remember that it will save you many sleepless nights.
[edit] Basic Templating
We are now going to show you how to develop templates to meet your real-world needs. Templates can be used in multiple places from basic forms to dynamic reports, simple web pages to extremely complex ones. In this section we will show you some great examples of Smarty templating and scripts to manage them.
Templates in the real world are a bit complex. To start, let's gain a basic understanding of logical conditions and loops.
[edit] Logical Conditions
Almost all programmers are familiar with logical conditions. Smarty TPL comes with useful logical statements that you can use in your templates. Smarty logic differs in syntax from PHP. In PHP, the scope of if is defined by braces, but in Smarty the scope is defined by an {if}{/if} block. All PHP conditional operators are supported by Smarty {if}. Let's look at the following comparison operator table taken from the Smarty manual:
| Qualifier | Alternatives | Syntax Example | Meaning | PHP Equivalent |
|---|---|---|---|---|
| == | eq | $a eq $b | equals | == |
| != | ne, neq | $a neq $b | not equals | != |
| > | gt | $a gt $b | greater than | > |
| < | lt | $a lt $b | less than | < |
| >= | gte, ge | $a ge $b | greater than or equal | >= |
| <= | lte, le | $a le $b | less than or equal | <= |
| === | $a === 0 | check for identity | === | |
| ! | not | not $a | negation (unary) | ! |
| % | mod | $a mod $b | modulus | % |
| is [not] div by | $a is not div by 4 | divisible by | $a % $b == 0 | |
| is [not] even | $a is not even | [not] an even number (unary) | $a % 2 == 0 | |
| is [not] even by | $a is not even by $b | grouping level [not] even | ($a / $b) % 2 == 0 | |
| is [not] odd | $a is not odd | [not] an odd number (unary) | $a % 2 != 0 | |
| is [not] odd by | $a is not odd by $b | [not] an odd grouping | ($a / $b) % 2 != 0 |
To define various conditions, Smarty also supports {elseif} and {else}. Let's go through an example to show Smarty {if} {else} {/if} in action.
sample_if.tpl
<table>
<tr><td>Name</td><td>Roll</td><td>Grade</td></tr>
<tr>
<td>{$student‑>name}</td>
<td>{$student‑>roll}</td>
{if $student.grade='F'}
<td bgcolor='red'>Failed</td>
{else}
<td bgcolor='green'>Passed</td>
{/if}
</tr>
</table>
This {if} block, changes the table cell color according to the supplied grade of a student. If the grade is F, it will be shown in a red background. Otherwise, green. You can write multiple conditions using the {if} {elseif} {elseif} {else} {/if} style. In Smarty, you can also implement a nested {if} {/if} block.
[edit] Loops
In Smarty, you can perform loops with two different tags. One is {section} and the other is {foreach}. Both of them are significant in different scenarios. {section} is very helpful when programmers supply the arrays in non‑associative style. You can traverse through the index of an array. In this tutorial you have already seen some examples of {foreach}. We will discuss them a bit more in this section.
{section} needs two parameters, name and loop, where name could be anything alphabetical and increases in each iteration. The other required parameter is loop. This is the name of the supplied array variable through which the {section} loops. But how many times does the loop iterate? This depends on the number of items in the supplied array, or anything you specified exclusively. {section} has four more optional parameters. One is start, which determines the initial counter, step is the increment, max is the maximum value that the {section} will loop, and a Boolean parameter show, which determines whether the {section}{/section} block will be displayed or not.
sample_section.tpl
{section name=my_loop loop=3}
I am Looping <br/>
{section}
Just note that we didn't supply any array here. If you run this, this will simply print:
'''I am looping''' '''I am looping''' '''I am looping'''
sample_section2.tpl
<table>
{section name=id loop=$titles}
<tr>
<td><tmg src={$images[id]}</td>
<td>Title: {$titles[id]}<br/>
Price: {$price[id]}<br/>
Author: {$authors[id]}</td>
</tr>
{/section}
Let's write a small PHP script that will fetch book data from your database and supply them to your template.
sample_section2.php
<?
#...your mysql connection & smarty initialization goes here
$result = mysql_query(SELECT title, image, price, author from books LIMIT 20);
while ($row = mysql_fetch_assoc($result)
{
$titles[] = $row['title'];
$images[] = $row['image'];
$prices[] = $row['images'];
$authors[] = $row['author'];
}
$smarty‑>assign("titles",$titles);
$smarty‑>assign("images",$images);
$smarty‑>assign("prices",$prices);
$smarty‑>assign("authors",$authors);
$smarty‑>display("sample_section2.tpl");
?>
If you run the script then you see the following output:
Just take a look at the code once again and note that the {section} loops with the $titles array. As the id increments, we can use other assigned arrays with this id in the {section} scope. Here, all the supplied arrays are non‑associative.
[ Though the {section} name increments, you can't display it as {$section_name}. You have to use some built‑in properties of the {section} tag. ]
{Section} has some built‑in variables that give you extra facility and control its attributes. These are discussed below.
[edit] index
index shows you the current loop index of the loop. This is very helpful if you want to display a serial number or if you want to process a particular loop index. It is used as shown here:
{section name=id loop=3}
This is loop index {$smarty.section.id.index}<br/>
{/section}
This will output
''' This is loop index 0''' ''' This is loop index 1''' ''' This is loop index 2'''
[edit] first
first gives you the first index of the loop. Usually this is zero, but this could be overridden if you specify the starting index by start attribute of {section}. You can use first to initialize if anything needs to be done before the further iterations. For example, you can check this:
{if $smarty.section.section_name.first}
<h2>This is Heading</h2>
{else}
do what ever you want
{endif}
[edit] iteration
iteration is similar to index but returns the current iteration number. If you loop three times with the start attribute set to ten, then index will return 10, 11, and 12 respectively; but iteration returns 1, 2, and 3. This is the main difference between index and iteration. iteration has an alias with a similar functionality. This is rownum.
[edit] total
This returns the total number of iterations. Note that this is the only variable you can use after the {section} ends.
[edit] loop
loop returns the last index number of the loop, which you can use after the loop or inside it.
[edit] foreach
{foreach} provides a great facility over {section}. With {foreach} you can iterate through the items of an array and access their properties much more easily as compared to {section}. I personally prefer to use {foreach} all the time. It extracts each item of the array as a separate array containing key-value pairs. You can access each and every property of that extracted object in an associative style. This increases the readability of your code and makes it easy for other team members who work with this code. For example, if you run a query in your database and then fetch the results preserving their keys (that is, using the mysql_fetch_assoc() function) and pass them to Smarty, then the {foreach} loop will extract each row from this whole result set as an associative array. You can access the data of every column for that row in this format: $object.propertyname. This makes your code much more structured and readable. If you want to convert the {section} example shown in the previous section into a {foreach} example, it will look like this:
sample_section2.tpl
<table>
{foreach item=book loop=$books}
<tr>
<td><tmg src={$book.image_id}</td>
<td>Title: {$book.title}<br/>
Price: {$book.price}<br/>
Author: {$book.authors}</td>
</tr>
{/section}
and the PHP code will be as shown:
sample_section2.php
<?
#...your mysql connection & smarty initialization goes here
$result = mysql_query(SELECT title, image, price, author from books LIMIT 20);
while ($row = mysql_fetch_assoc($result)
{
$book['title'] = $row['title'];
$book['image_id'] = $row['image'];
$book['price'] = $row['images'];
$book['authors'] = $row['author'];
$books[] = $book;
}
$smarty‑>assign("books",$books);
$smarty‑>display("sample_section2.tpl");
?>
[edit] Templates in the Real World
Now that we have discussed the basics, let's see how templates work in real-world problems. We will show you how to develop some templates that can solve your everyday problems. These are listed below:
- Calendar
- Generalized Database Reports
- Data Input Forms
- Email Newsletter
[edit] Calendar
Calendar is a HTML gadget you may occasionally need for a website. If you plan to develop a calendar, don't worry about writing many lines of code. Using Smarty, you can develop it in a very straightforward way. Let's see how.
calendar.tpl
{$title}
{html_table loop=$special_days cols=7}
</body> </html>
In this template, we use a special Smarty function named {html_table}. We will discuss this in detail, later in this section. First let's take a look at the PHP script that assigns the variables to display the calendar.
calendar.php
<?
include("libs/smarty.class.php");
$smarty = new smarty();
$date = "10/01/2005"; //October 01, 2005
$week_days = array("Sat"=>1, "Sun"=>2, "Mon"=>3,"Tue"=>4,"Wed"=>5, "Thu"=>6,"Fri"=>7);
$total_day_of_month = get_total_day($date);
$starting_day = $week_days[Date("D",strtotime($date))] - 1;
foreach (array_keys($week_days) as $day)
$days[] = $day;
for ($i=0; $i<$starting_day; $i++)
$days[] = " ";
for ($i=1; $i< ($total_day_of_month+1); $i++)
$days[] = $i;
$smarty->assign("title","October 2005");
$smarty->assign("special_days", $days);
$smarty->display("calendar.tpl");
function get_total_day($date)
{
$time_stamp = strtotime($date);
$month_ar = split("/", $date);
$month = $month_ar[0];
$year = Date("Y",$time_stamp);
for ($i=28; $i<33; $i++)
{
if (!checkdate($month, $i, $year)){
return ($i - 1);
}
}
}
?>
If you run this script in a browser you will see the following output:
Note that in the code, we supplied the date in the $date variable. If you change it to 11/01/05 then you will see the following output.
That's it, you're done!. Have you noticed how small the template is? As we said, we use a special Smarty function {html_table}. This takes an array as parameter and an optional column number. By default the column number is set to 3. Here we need seven columns for a calendar, so we specified cols=7. Then it displays the array as a table splitting it into specified number of columns in each row.
[edit] Database Report
Database reports are the most common examples where Smarty is used. With Smarty, you can develop smashing reports in a minute. However, if you want to your reports to look good, you must have some knowledge about CSS. For this example, we have the following tables:
mysql> DESC agents;
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| area | varchar(50) | ||||
| agent_id | int(11) | 0 | |||
| agent_name | varchar(255) |
mysql> DESC items;
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| item_id | varchar(10) | ||||
| item_name | varchar(255) | ||||
| item_price | int(11) | 0 |
mysql> DESC sales;
| Field | Type | Null | Key | Default | Extra |
|---|---|---|---|---|---|
| agent_id | int(11) | 0 | |||
| item_id | varchar(10) | 0 | |||
| quantity | int(11) | 0 |
3 rows in set (0.00 sec)
database_report.php
<?
include("libs/smarty.class.php");
$smarty= new smarty();
mysql_connect("localhost","root","root");
mysql_select_db("smarty");
$result = mysql_query("SELECT area,
agent_name,
item_name,
quantity,
item_price,
(quantity*item_price) as total
FROM agents
INNER JOIN sales on agents.agent_id = sales.agent_id
INNER JOIN items on sales.item_id = items.item_id
ORDER BY area ASC");
while ($row = mysql_fetch_assoc($result))
{
$areas[] = $row['area'];
$agents[] = $row['agent_name'];
$items[] = $row['item_name'];
$quantities[] = $row['quantity'];
$total[] = $row['total'];
}
$fields = array("area", "agent", "item", "quantity", "total");
$smarty->assign("areas", $areas);
$smarty->assign("agents", $agents);
$smarty->assign("items", $items);
$smarty->assign("quantities", $quantities);
$smarty->assign("total", $total);
$smarty->assign("fields", $fields);
$smarty->display("database_report.tpl");
mysql_free_result($result);
?>
This script executes a query and fetches the records. It then makes an array of each item and assigns it to a Smarty variable. Now, it's time to develop the template for the report. Let's go.
database_report.tpl
<html>
<body>
<table cellpadding="4" border="1" cellspacing="0"><tr>
{section name=id loop=$fields}
<th>{$fields[id]}</th>
{/section}
</tr>
{section name=data loop=$areas}
<tr>
<td>{$areas[data]}</td>
<td>{$agents[data]}</td>
<td>{$items[data]}</td>
<td>{$quantities[data]}</td>
<td>{$total[data]}</td>
</tr>
{/section}
</table>
</body>
</html>
Now run this script and you will get the following output:
You get a basic database report with not much attention paid to its presentation and look. The template code is so simple that Smarty beginners can easily understand it. Let's see how we can make this report look better with another Smarty function, cycle.
cycle is a Smarty function that just cycles through a set of values and returns them one by one. This function is extremely useful when you are trying to choose alternating values for a specific purpose. For an example, if we change the background color of every <tr> element then definitely it will look more pleasant. Let's see the {cycle} function in action. Just replace the <tr> on the ninth line in the above template with the following code:
<tr bgcolor='{cycle values="#EBEBEB, #ACABAB"}'>
Now run the script and you will see the following output:
Smarty gives you extremely powerful functions for doing everything you would like to.
Let's apply some CSS over your template. We will just change the <th> style, and remove the table border and add the following style definition at the beginning of the database_report.tpl file.
<style>
#report_table th{
border: 1px solid;
/*padding‑left: 15px;*/
padding‑right: 30px;
color: #EEEEEC;
background‑color: #25510D;
text‑align: left;
}
#report_table {
border: 1px solid #cccccc;
}
</style>
We will also replace the third line of our previous template code with this one:
