PHP Tutorial

Step 3

PHP Tutorial

In this tutorial we will create a simple twitter copycat. In step 3 we will separate the presentation and business layers by using Smarty.

Step 3

1. If we take a look into the source code of our list_all.php file, we can see that it has clearly two different parts. The first part deals with fetching all necessary data from the database:

<?php
  include_once('../../config/init.php');
  include_once($BASE_DIR .'database/tweets.php');

  $tweets = getAllTweets();  
?>

While the second part is responsible for presenting that data in HTML format:

<!DOCTYPE html>
<html>
  <head>
    <title>Example Twitter</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="<?=$BASE_URL?>css/style.css">
  </head>
  <body>
    <section id="tweets">

      <header>
        <h2>Tweets</h2>
      </header>

      <?php foreach ($tweets as $tweet) { ?>
      <article class="tweet">
        <header>
          <span class="realname"><?=$tweet['realname']?></span>
          <a href="#" class="username">@<?=$tweet['username']?></a>
          <span class="time"><?=$tweet['time']?></span>
        </header>

        <p><?=$tweet['text']?></p>
      </article>
      <?php } ?>

    </section>
  </body>
</html>

Having the first part clearly separated from the second one is very important, as it promotes better code readability. Separating these two parts into different files would be even better, as it would allow any of those parts to be reused easily. But we can do even better than that.


2. A template processor (also known as a template engine or template parser) is a software component designed to combine templates with a data model to produce documents.

DATA + TEMPLATE = DOCUMENT

In our case we already have our data in the form of a PHP array and we already know that we want to generate an HTML document. But why use a template processor at all? There are several reasons:

In this tutorial we will use a very common template processor called Smarty.


3. To use Smarty, the first thing we will need to do is to add a new folder to our project that will hold any used libraries. We will call this folder lib. Inside this folder we will add another one called smarty that will hold the Smarty code.

In a typical project this code should be located outside the project folder so it could be reused by several projects but for simplicit sake and for the project to be self contained we will keep it all together.

Our folder structure should now look like this:

   css/
   pages/tweets/
   database/
   config/
   lib/smarty/

4. We will now download Smarty’s last stable release from here source code from here, unzip it and copy the contents of the Smarty-x.x.xx/libs/ folder to our lib/smarty/ folder.


5. Now we need to include Smarty in all our pages so we can use it whenever we want. To do that we will add the following line to our config/init.php file:

  include_once($BASE_DIR . 'lib/smarty/Smarty.class.php');

To use Smarty we need to instanciate it first. We can do this by adding the following line to the same file:

  $smarty = new Smarty;

This will create a new $smarty object that we can use in all of our pages.


6. Smarty templates are written in a language not very different from PHP. You can learn more by taking a look at a brief crash course, a comparison between Smarty and PHP and the complete documentation.


7. Smarty templates should be stored in files with a .tpl extension in a special folder called templates. We will now create this folder and also another one called tweets inside it. This last one, will contain all templates related to tweets. Our folder structure should now look something like this:

  css/
  pages/tweets/
  templates/tweets/
  database/
  config/
  lib/smarty/

8. Inside this new folder we will create a new file called list.tpl. This file will contain the template for listing tweets. We don’t call it list_all.tpl because the template is agnostic to which tweets it is listing.

We will then move the presentation code from our list_all.php file to this new file (see point 1. above) and modify it to fit into a Smarty template:

<!DOCTYPE html>
<html>
  <head>
    <title>Example Twitter</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="{$BASE_URL}css/style.css">
  </head>
  <body>
    <section id="tweets">

      <header>
        <h2>Tweets</h2>
      </header>

      {foreach $tweets as $tweet}
      <article class="tweet">
        <header>
          <span class="realname">{$tweet.realname}</span>
          <a href="#" class="username">@{$tweet.username}</a>
          <span class="time">{$tweet.time}</span>
        </header>

        <p>{$tweet.text}</p>
      </article>
      {/foreach}

    </section>
  </body>
</html>

As you can see, Smarty and PHP’s syntaxes are very similar; we use curly brackets, instead of less than and greater than symbols, and use a period to specify an array’s index instead of square brackets.


9. Our template uses two variables, $BASE_URL and $tweets, that Smarty doesn’t know about. Every variable used in Smarty has to be explicitly passed from our PHP code. To solve this we have two make to simple modifications. In the config/init.php file we add the following line:

  $smarty->assign('BASE_URL', $BASE_URL);

And in the list_all.php file we add this one:

  $smarty->assign('tweets', $tweets);

The first parameter of the assign function is the name the variable will be known by in Smarty, the second one is its original name in PHP.

10. The last step will be to diplay our template from the list_all.php file. To do that just add this line to this file:

  $smarty->display('tweets/list.tpl');

Not so fast. Just one more thing before we are done. Smarty assumes that our templates folder is at the same level as the PHP page we are executing. As our list_all.php page is two levels down the folder structure, we have to add two more lines to our config/init.php file, right after instantiating Smarty:

  $smarty->template_dir = $BASE_DIR . 'templates/';
  $smarty->compile_dir = $BASE_DIR . 'templates_c/';

The templates_c folder is where Smarty compiles its templates into PHP code. You don’t have to worry about those files.

And now we are done for this step. By the way, our list_all.php file should be as simple as this:

<?php
  include_once('../../config/init.php');
  include_once($BASE_DIR .'database/tweets.php');

  $tweets = getAllTweets();  

  $smarty->assign('tweets', $tweets);
  $smarty->display('tweets/list.tpl');
?>

You can find the complete code after step 3 here. In step 4 we will organize our template code.