PHP DevCenter

oreilly.comSafari Books Online.Conferences.

We've expanded our LAMP news coverage and improved our search! Search for all things LAMP across O'Reilly!

Search
Search Tips

advertisement

Listen Print Discuss Subscribe to PHP Subscribe to Newsletters

Modular PHP Development with FastTemplate
Pages: 1, 2

A Working Example

We now have a good framework to work with, so let's see how to implement a web page with this technique. To start, we'll need to write a template that defines the layout of the page, language files that hold the texts for our two fake web sites, and a PHP file that incorporates the template, the texts, and some additional logic into an actual web page. Four files will be created:



  • index_php.html (the template)
  • index_php_com.lang (the texts in English)
  • index_php_se.lang (the texts in Swedish)
  • index.php (the logic)

Remember that the language file included will be based on the name of the host on which the PHP script is currently executing. For this example, I have set up two fake servers: http://www.myfakedomain.com/ and http://www.myfakedomain.se/. To use the same files, they must both use the same document root. These are the virtual host directives that were added to Apache's httpd.conf for these two hosts:

<VirtualHost *>
    DocumentRoot /usr/local/apache/htdocs/myfakedomain
    ServerName www.myfakedomain.com
</VirtualHost>
 
<VirtualHost *>
    DocumentRoot /usr/local/apache/htdocs/myfakedomain
    ServerName www.myfakedomain.se
</VirtualHost>

We now have to place the four files listed above in /usr/local/apache/htdocs/myfakedomain.

Let's start with the template. It's the same for both sites, although you could use the TLD technique on that one very easily as well. The common way, however, is to use the same layout, and provide it in several different languages. index_php.html is listed below, just as it looked when we got it back from the designer at MyFakeDomain):

<html>
<head>
<title>{TITLE}</title>
</head>
<body bgcolor='lightblue'>
<center>
<font color='blue'>
<font face='arial' size='4'><b>{HEADING}</b></font>
<font face='arial'><p>{TEXT}</p>lt;/a>
<table border='1' bgcolor='darkblue'>
<tr>
<th>
<font color='yellow'>{NAME}</a>
</th>
<th>
<font color='yellow'>{POSITION}</a>
</th>
</tr>
<!-- BEGIN DYNAMIC BLOCK: employees -->
<tr>
<td>
<font color='yellow'>{C_FIRSTNAME} {C_LASTNAME}</font>
</td>
<td>
<font color='yellow'>{C_POSITION}</font>
</td>
</tr>
<!-- END DYNAMIC BLOCK: employees -->
</table>
<font face='arial'><p>{LOCAL_TIME}: <b>{C_LOCAL_TIME}</b></p></font>
</font>
</center>
</body>
</html>

This is an ordinary HTML document with two important differences. As you see, there's no actual text in it, only FastTemplate constants. These constants, which always must be wrapped inside curly brackets, will be replaced by actual text when the template gets parsed. Also, there is a dynamic block, called employees, defined in this template. The PHP logic will identify this block and repeat it as many times as it finds required, each time generating a table with a dynamic number of rows in it. There's nothing special about that, you might be thinking, but here we are doing it from a plain HTML template, without any ugly logic in there at all.

To see which FastTemplate constants are really constant (that is, defined in one of the language files), and which ones are generated at execution-time by the PHP logic, I like to add the prefix C_ to the generated constants. In my world, C stands for "current", but you can of course use whatever you want. Just make sure you agree with yourself on a standard.

The language files, one received from the English-speaking marketing guy and the other received from the Swedish-speaking, define the constant texts in the template. The English version, index_php_com.lang is listed below:

<?
$text = array(
    'TITLE'        => "Welcome to MyFakeDomain",
    'HEADING'      => "MyFakeDomain",
    'TEXT'         => "Below is a listing of all employees at MyFakeDomain:",
    'NAME'         => "Name",
    'POSITION'     => "Position",
    'LOCAL_TIME'   => "Local time"
);
?>

The text snippets are defined in an array called $text. If you remember, we assigned the contents of this array to FastTemplate in header.php at line 8. Since the name of this array is hardcoded into header.php, it must go by the name $text in all language files.

The Swedish version of the language file, index_php_se.lang looks almost the same, but this time, the actual texts are written in Swedish:

<?
$text = array(
    'TITLE'        => "Vlkommen till MyFakeDomain",
    'HEADING'      => "MyFakeDomain", 
    'TEXT'         => "Nedan finns en lista ver de anstllda p MyFakeDomain",
    'NAME'         => "Namn", 
    'POSITION'     => "Position",
    'LOCAL_TIME'   => "Lokal tid"
); 
?>

One of these language files will be included and assigned to FastTemplate in header.php. That will determine in which language to present the information. For this example, we have only two language files since we only have two web sites. However, you could have ten, twenty, or a thousand different language files and sites, and this technique would work equally well.

Finally, we'll also need some PHP logic to tie the texts and the template together into a complete web page. This PHP code also needs to generate the dynamic constants we referred to in the template (the ones starting with a C_), and also parse through the dynamic block (employees). The script that does all this is, of course, called index.php:

1:  <?
2:     include_once ("header.php");
3:  
4:    $people[] = array(
          'firstname' => "John",
          'lastname'  => "Doe",
          'position'  => 'Developer');
5:    $people[] = array(
          'firstname' => "Sven",
          'lastname'  => "Svensson",
          'position'  => 'Web Designer');
6:    $people[] = array(
          'firstname' => "Jose",
          'lastname'  => "Perez",
          'position'  => 'Head of Marketing');
7: 
8:     $tpl->define_ dynamic(" employees","page");
9:     foreach ($people as $person)
10:    { 
11:        $tpl->assign( array(
12:            'C_FIRSTNAME'      => $person['firstname'],
13:            'C_LASTNAME'       => $person['lastname'],
14:            'C_POSITION'       => $person['position']
15:        ));
16:        $tpl->parse( ROWS,".employees");
17:    }
18:
19:    $tpl->assign( array('C_LOCAL_TIME' => date("H:i:s")) );
20:
21:    include_once ("footer.php");
22: ?>

We always need to include header.php at the top of every PHP file, so we do that directly at line 2. Now remember that when line 2 is finished, FastTemplate has been set up, and the correct template file and language file has been included and assigned to FastTemplate.

On line 4, 5 and 6, we create an example array, called $people, of employees at our fictive company. This array is created so that we have some sample data to use with our dynamic block in the template (employees). For a real application, this could have been replaced by a call to a database or a request to a web service.

Line 8 tells FastTemplate about the dynamic row. We do this by calling FastTemplate->define_dynamic(), passing the name of the dynamic block and the name of the template in which the dynamic block appears as parameters. Note that the name of the template should not be the name of the actual file, but the name we assigned to it when registering it to FastTemplate (line 9 in header.php).

Lines 9 through 17 iterate through $people. Each row of the array is assigned to the constants C_FIRSTNAME, C_LASTNAME, and C_POSITION (lines 11 through 15), and is then parsed into the dynamic block (line 16). Also note how the call to FastTempate->parse() differs a little from the call we make in footer.php; here we use a leading . (dot) on the template name (which in this case is a dynamic block) to tell FastTemplate that we want to append information to the value ROWS, and not truncate it. Then, when FastTemplate->FastPrint() is called in footer.php, the dynamic block in the template will be replaced by the value of ROWS.

On Line 19 we define the constant C_LOCAL_TIME, which, if you remember, was referred to in index_php.html. As you see, we use date() to generate a string representing the current time (in the format HH:MM:SS), storing that string in C_LOCAL_TIME. Since the value of this constant is calculated upon each request, every page will show the current time.

As outlined by the framework, we need to include footer.php at the end of each PHP file. We do that at line 21.

Everything seems to be in place now. We have the template, the texts, and the logic. Let's test it! On my local network, I have set up the fake zones myfakedomain.com and myfakedomain.se on the name server, and I've pointed www.myfakedomain.com and www.myfakedomain.se to the web server. When I direct my browser at http://www.myfakedomain.com, I see a page similar to Figure 1.

English content
Figure 1. Content in English

If I make a request to http://www.makefakedomain.se, I'll see something more like Figure 2.

Swedish content
Figure 2. Content in Swedish

Both sites have the same layout and the same logic, but with different texts. This is the result of three independent modules tied together!

Summary

After making this technique the standard at the company I work for, both web designers and people involved in text development have a good understanding how this work. By setting up and configuring FTP clients on their machines, they can check out existing templates or language files, make changes to them, and upload them back to the server. Dynamic web pages on our site are updated in no time, without the involvement of any technical staff. If text needs to be removed, a marketing person simply sets that variable to empty in his or her language file. If a particular text snippet should be removed from all versions of a web page, the marketing people just asks a web designer to remove the reference to that particular constant in the template.

Sometimes the marketing people decide they want some additional dynamic content added to a web page. For example, once one of the web designers called me and said "Hey Daniel! You know, X at marketing called and said she and Y had decided they want to present our current price of Z on the front page. I added a reference to c-underscore-z-underscore-price in the template, so do you think you could get me that variable from the database?" I just added some additional logic to the PHP file for our front page that connected to our database, retrieved the current price of Z, and stored the price in FastTemplate as C_Z_PRICE (of course, with Z replaced by the real name of that product). The marketing people got what they wanted in half an hour or so, everyone doing only their part of the work.

If needed, this concept also allows moving some of the design into the language files when needed. For example, it might turn out useful to use a constant from a language file to set the background colour for a page or table, or the font for some text. By this, marketing people can control some of the layout without the involvement of a web designer. This can be good if the web designer is not available, and the marketing people have a scheduled change for a particular page. However, after I discover this kind of abuse, I usually try to look at them with a little annoyed grin on my face when I meet them in the corridor. Everyone should do what they are supposed to; that's the whole idea.

Finally, you should keep in mind that the original FastTemplate distribution for PHP doesnt work very well with PHP4. I used the PHP4-compatible version of FastTemplate for this example. If you use PHP3, or are looking for the official documentation, take a look at http://www.thewebmasters.net/.

I hope you will find the techniques presented in this article useful.

Daniel Solin is a freelance writer and Linux consultant whose specialty is GUI programming. His first book, SAMS Teach Yourself Qt Programming in 24 hours, was published in May, 2000.


Return to the PHP DevCenter.



Have a question about how to apply Daniel's techniques? Ask him here.
You must be logged in to the O'Reilly Network to post a talkback.
Post Comment
Full Threads Oldest First

Showing messages 1 through 16 of 16.

  • FastTemplate define_dynamic
    2008-10-09 03:09:25  LeHHeL [Reply | View]

    Fast Template is still alive, check it at http://www.grafxsoftware.com/product.php/Fast-Template/26/
  • It seems the templating languages are as complex as PHP
    2004-11-04 07:41:21  leecarmichael [Reply | View]

    I guess I don't understand how changing:

    <title> <?= $LANG["title"] ?></title>
    or
    <title> <?= $TITLE ?> </title>

    is anymore complex than:

    <title> {{ TITLE }} </title>

    I am really having a hard time understand why you would ever want to add a templating language to a templating language. I can understand why you would still want to use the 'controller' -> 'view' design to hide the annoying details of how forms are processed and data retrieval and such. But it seems that it would be more simple to have a single language used on a website (php instead of php and fast template, smarty or ....). Also it seems that most web editors (such as dreamweaver) can handle understanding php tags.

    What am I missing?
  • YATS
    2004-04-11 16:36:48  andreanderson [Reply | View]

    Great article. Your readers may also be interested in YATS (http://yats.sourceforge.net). This is a PHP extension that behaves a lot like FastTemplate, but is *much* faster and provides additional functionality -- while still focusing on templating, not coding.
  • Templates the way to go
    2003-12-17 09:13:55  anonymous2 [Reply | View]

    Just a few notes on my experiences with templates:

    I have the privilege(?) of being the designer, programmer and marketing person for a medium sized company European company that provides its website in 7 languages. I took the approach of using fast template for the current incarnation of our site.

    I took templating to the extreme level by removing ALL content/text from the templates so that I could use a standard set of templates and programmes for all 7 language version with all of the language translations stored in a set of config and 'include at run-time text' files.

    This meant that the people providing the translations had simple files to translate and that I instantly divided my support problems by 7 - I was only solving the problems once for all versions of the site - thus fixing all 7 versions in one go.

    There is no way I would ever have finished the 7 versions without templating.

    Fast template and all of the including I have to do does add a slight load to the server - but the benefits in the development/maintenance are well worth the extra couple of milliseconds per page.

    I don't think I would ever consider doing a large PHP project again without using templating - just being able to seperate the different 'mind-sets' (programmer/designer) helps no end.

    I am currently rewriting the site using Smarty - its template compiling and caching functions remove the whole server load issues - even speeding up site a little - and its extra 'ready to use' built-in functions make the actual programmes simpler.

    I agree that Smarty does make the templates more complicated for the webdesigner ( but as this is me too there is no problem for me :-) ) - but as I am switching from a tables/pixel.gif based layout to a standards based CSS layout the templates are producing nothing more than well structured text documents.

    Now if only I could get a three column layout in CSS to work properly...
  • Do your own :)
    2003-11-01 19:18:58  anonymous2 [Reply | View]

    Make your own class to define variables for a specific(data-wise) template, includes the template from a proper php file and let the class function to parse it using preg_replace(). This is what i am doing. You can also make a simple class which simply does the parsing only. :)
  • Fasttemplate alternative
    2003-10-15 01:09:25  anonymous2 [Reply | View]

    This one is simpler to use, and was created in response to the complexity of fasttemplate.

    http://templatepower.codocad.com/
    • RE: Fasttemplate alternative
      2003-10-15 01:16:13  dsolin [Reply | View]

      Hi there,

      Thank you very much for this tip. TemplatePower surely proves to be a another good alternative to FastTemplate. Anbd, as far as I can see, TemplatePower also use regular HTML-comments to define template blocks. Very nice.

      All best,
      Daniel
  • other solution...
    2003-10-04 11:59:03  anonymous2 [Reply | View]

    You 've got another solution that looks like FastTemplate but it's faster and that manages 8 database throw PEAR DB and has a good documentation

    TPLN - Template Processor
    http://tpln.sourceforge.net
    • other solution...
      2003-10-08 17:06:27  anonymous2 [Reply | View]

      There is also PHP-TAL: http://phptal.sourceforge.net/.
      TAL stands for the Template Attribute Language and manages to survive Dreamweaver edits by putting the template hints in as tag attributes. So instead of using <-- BEGIN BLOCK --> you would do something like <tr tal:repeat="item here/someRepeater">.
    • other solution...
      2003-10-05 11:51:37  dsolin [Reply | View]

      Hi!

      Thanks for this tip. TPLN definitely looks like a good alternative to FastTemplate. Please note, however, that this article doesn't actually try to promote FastTemplate, but rather the clean modular design you can accomplish by using it (or any other similar template engine, just as you suggest).

      All best,
      Daniel
  • neverer seen the point of templates
    2003-10-03 06:14:27  anonymous2 [Reply | View]

    Modular PHP dev is ok , but why you need FastTemplate or Smarty or whatever template system ?!
    OOP slows php down and u're using a tank to kill a fly .
    my opinion
    • neverer seen the point of templates
      2007-07-24 11:21:08  W3prodigy [Reply | View]

      As everyone else has mentioned, OOP doesn't slow anything down. The only time a server will be slowed down is by A) referrencing an outside connection, or B) Outputting to the buffer, causing more memory to be used by your server.

      OOP is very portable, at least that's why I use it.
    • neverer seen the point of templates
      2003-10-10 01:34:37  tychay [Reply | View]

      How do you propose to do modular design without a templating system? While I only skimmed the article, it seems the author has it "right on." If you ever had to work with designers before, you'll immediately see the benefits for non-intrusive templating languages like FastTemplate, SmartTemplate, etc. over raw PHP.

      If you have the luxury of not having to work with any designers then there is no need to separate "the PHP code" from the templates... no need for modularity.

      In other words, like all OOP design, templating gives you the flexibility in a certain direction. If you don't need that flexibility, you don't need templating.

      BTW, OOP does not slow PHP4 down significantly more than an associative array and a bunch of functions, because that's how PHP4 treats it (much to the headache of a lot of PHP programmers I might add). Of course, things will be even more optimized with PHP5.

      Take care,

      terry chay
    • neverer seen the point of templates
      2003-10-06 22:44:06  anonymous2 [Reply | View]

      It's been well noted on the PHP lists that OOP does not slow down PHP in any significant way. I've seen OOP scale quite well on a site with 30M hits a month.

      BEWARE OF THE FUD ...
    • neverer seen the point of templates
      2003-10-05 11:57:39  dsolin [Reply | View]

      Hello,

      Hmm... I'm not quite sure what you mean here. How do you mean we (easily) could accomplish the same modular design without using some kind of template system? If you got a better solution, we would all love to see it.

      Best wishes,
      Daniel
      • neverer seen the point of templates
        2003-12-28 14:36:39  anonymous2 [Reply | View]

        Me neither :D That is why I now use PHPs DOMXML extension to dynamically build a page as and when it is required :)

        Works like a dream in the design of Model View Controller archetechture folks...


Tagged Articles

Be the first to post this article to del.icio.us

Sponsored Resources

  • Inside Lightroom
Advertisement

Sponsored by:

O'Reilly Media

©2009, O'Reilly Media, Inc.
(707) 827-7000 / (800) 998-9938
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
About O'Reilly
Academic Solutions
Authors
Contacts
Customer Service
Jobs
Newsletters
O'Reilly Labs
Press Room
Privacy Policy
RSS Feeds
Terms of Service
User Groups
Writing for O'Reilly
Content Archive
Business Technology
Computer Technology
Google
Microsoft
Mobile
Network
Operating System
Digital Photography
Programming
Software
Web
Web Design
More O'Reilly Sites
O'Reilly Radar
Ignite
Tools of Change for Publishing
Digital Media
Inside iPhone
O'Reilly FYI
makezine.com
craftzine.com
hackszine.com
perl.com
xml.com

Partner Sites
InsideRIA
java.net
O'Reilly Insights on Forbes.com