Thursday, January 17, 2008

Learn Smarty

The most common complaint that comes when a designer and a programmer are working together on the same project is that the output is mostly bugged. The reason for this is that the designer doesn't like too much funny symbols and characters in his HTML and tries to clear some of them. Erasing a single semicolon can cause a bunch of errors in PHP. This mostly results in arguments and blames. Yet on the other hand, it is important that the project is completed within the deadlines and hence we cannot seperate them from working together that easily. Lets see a few examples.


(html)
(head)
(title)
(?php
echo $title;
?)
(/title)
(/head)
(body)
(?php
echo "This is my first smarty example";
?)
(/body)
(/html)


The above example doesn't seem that bad. But trust me, when you start putting some complex pieces of code inside, it gets way too much messy.

Now lets start with some database queries.

(?php
//db configuration
include "config.php";

if(!($db = @mysql_connect($server, $db_user, $db_pass))) //connect to database
die("Couldn't connect to the database.");
if(!@mysql_select_db($db_name, $db)) //select database
die("Database doesn't exist!");

$sql = "SELECT * FROM users";

if(($result = @mysql_query($sql, $db)) == 0)
{
echo "\n(hr /)Database error: (span)".mysql_error()."(/span)(br/)\n";
die("MySQL Said: " . mysql_error());
}

$user = array();

?)
(table)
(tr)
(td)(b)Name(/b)(/td)(td)(b)Lastname(/b)(/td)
(/tr)
(?php
while($tmp = mysql_fetch_assoc($result))
{
?)
(tr)
(td)(?php echo $tmp["Name"];?)(/td)(td)(?php echo $tmp["Lastname"];?)(/td)
(/tr)
(?php
}
?)


The above code doesn't seem that messy because the HTML is still seperate from PHP (since we are not echoing it with PHP). Although the designer might still mess something if he is given this code to deal with. But this code doesn't seem that efficient when it gets bigger and bigger.
The general practice is that the programmer start echoing the HTML within PHP. Lets make the code a little easier with our own template system now.

(?php
//db configuration
include "config.php";

if(!($db = @mysql_connect($server, $db_user, $db_pass))) //connect to database
die("Couldn't connect to the database.");
if(!@mysql_select_db($db_name, $db)) //select database
die("Database doesn't exist!");

$sql = "SELECT * FROM users";

if(($result = @mysql_query($sql, $db)) == 0)
{
echo "\n(hr /)Database error: (span)".mysql_error()."(/span)(br/)\n";
die("MySQL Said: " . mysql_error());
}

$user = array();

while($tmp = mysql_fetch_assoc($result))
{
$user[] = $tmp;
}

include "templates/myTemplate.tpl.php";
?)


This is the basic PHP code.
Now this is the template PHP file which is mostly HTML.

(html)
(head)
(title)My Own Template System(/title)
(/head)
(body)
(table)
(tr)
(td)Name(/td)(td)Lastname(/td)
(/tr)
(?php
for($i=0; $i(count($user); $i++)
{
?)
(tr)
(td)(?php echo $user[$i]["Name"];?)(/td)(td)(?php echo $user[$i]["Lastname"];?)(/td)
(/tr)
(?php
}?)
(/table)
(/body)
(/html)


This way the designer is only concerned with this above file. He doesn't need to know how the base PHP is working.
He only needs to know some small details about PHP and he is good to go. Although There is a better way than this.

Using Smarty Template Engine


At first, like most PHP developers, I tried to stay away from this Template Engine because it was way too complex for me to understand and the necessary files that i though it used to create. Although as time passed, I realized, it gets really hard to code you own template engine as good as Smarty. In the next example I will show you how to convert MyFirstTemplate to work with Smarty.
First of all, download the latest version of Smarty Template Engine . Once you downloaded it, extract it into the temporary dir.
Next thing to do is to setup all directories and files Smarty needs. It requires templates, templates_c, cache and configs directories. Templates dir should be used to place templates you create, templates_c is directory is for complied templates, cache for cached templates and configs for config files. However, you can name them however you want, but make sure you tell Smarty that. I created one more directory named smarty, where you should copy libs directory which comes along with archive you just downloaded.

At this point, you should have structure of your future web application like this:

- [cache]
- [configs]
+ [smarty]
- [libs]
- [templates]
- [templates_c]

Make sure to make templates_c and cache directory writable by your web server. You can do this be setting their CHMOD to 755 or 777, which ever your server

allows.
I have created a config file which will contain some basic configuration such as database info as well as some code which will be used for initializing

Smarty.

Here is the code within config.php file:

(?php

//db configuration
$server = "localhost";
$db_user = "root";
$db_pass = "password";
$db_name = "myFirst";


require_once("smarty/libs/Smarty.class.php");
$smarty = new Smarty;

?)

Now lets change our First Template with Smarty.

(?php
//db configuration
include "config.php";

if(!($db = @mysql_connect($server, $db_user, $db_pass))) //connect to database
die("Couldn't connect to the database.");
if(!@mysql_select_db($db_name, $db)) //select database
die("Database doesn't exist!");

$sql = "SELECT * FROM users";

if(($result = @mysql_query($sql, $db)) == 0)
{
echo "\n(hr /)Database error: (span)".mysql_error()."(/span)(br/)\n";
die("MySQL Said: " . mysql_error());
}

$user = array();

while($tmp = mysql_fetch_assoc($result))
{
$user[] = $tmp;
}

$smarty-)assign("title", "My First Template with Smarty");
$smarty-)assign("user", $user);
$smarty-)display("myFirstExample.tpl.htm");
?)


All we added was the last three lines of code.
Basically what we are doing here is that we are assigning some values to the variables we will use in our HTML template.
$smarty is the constructor variable. You can make your own with changing the config line "$smarty = new Smarty;" to $youVar = new Smarty;"

The last line of code tells Smarty to use this ("myFirstExample") file as the template.

The myFirstExample.tpl.html looks something like.

(html)
(head)
(title){$title}(/title)
(/head)
(body)
(table)
(tr)
(td)No(/td)
(td)Name(/td)(td)Lastname(/td)
(/tr)
{section name=i loop=$user}
(tr)
(td){$smarty.section.i.iteration}(/td)
(td){$user[i].Name}(/td)(td){$user[i].Lastname}(/td)
(/tr)
{/section}
(/table)
(/body)
(/html)


The advantage we got is that now we can preview our HTML code on the browser directly, and when we run it with PHP, it will work as it should.

The major change that you must have noticed is.

{section name=i loop=$user}
(tr)
(td){$smarty.section.i.iteration}(/td)
(td){$user[i].Name}(/td)(td){$user[i].Lastname}(/td)
(/tr)
{/section}


{section} is for a looping over arrays of data and each of section tags must be followed by closing tag {/section}. {section} tag requires only two

attributes: name and loop. Name attribute is a name of the section and loop is a value to determine the number of loop iterations. However, {section} has

other optional attributes such as start, stop, max, show.
{section} also has its own variables which handle section properties. One of them I used to show the number of iteration is echoed with

{$smarty.section.i.iteration}.
Also, you are able to nest sections within sections, however, make sure that you name those differently.

This is it, Smarty in some basic action. This code only shows how to install and use some basic options. There is so much to smarty, and I will try to show

you how to use modifiers, write your own and to take advantage of everything smarty offers.
I hope this was useful and you wouldn't need to code your own template engine for every application you make.

1 comment:

Chrisranjana.com software said...

Yes the designers we work with just love editing a smarty template rather than and embedded php coded template.



Php Developer