I don't know about you, but all these documents about dividing web
programming into logic, presentation, and content always irritate me.
Most of them miss an important point: often at least three people
develop a web page--the programmer (i.e, the PHP or Perl guru), the
web designer who provides the presentation (the HTML designer), and
the content developer (perhaps a marketing person). If you're working
for a multilingual company, you probably have to make the pages
available in several different languages as well, with one marketing
person responsible for each language. Most documentation on this
subject tends to forget, or at least doesn't bother to notice, either the
web designer or the marketing person.
I bring up this subject because, as the programmer, I'm usually the
one who has to come up with a solution. The marketing people simply
don't understand the problem. While the web designer probably
understands, he or she may not know how to solve it. When I point out
this issue at a project meeting, everybody looks at me with the
"you're the genius here, so come up with something brilliant!"
look. Genius or not, they're right.
This article will demonstrate how to divide logic from presentation and
presentation from content. In the end, a web page will consist of three files:
one PHP file with all page logic, one HTML file containing the presentation,
and one or more language files that will hold the texts for the page. The
language file to use for a specific request will be determined on-the-fly by
examining the current site. (www.mysite.com/index.php will
present information in English, www.mysite.se/index.php in
Swedish, and www.mysite.de/index.php in German.)
Choosing a Template Engine
To separate logic, presentation, and text into different files, we
need a template engine. Most PHP projects today use Smarty for this, but we won't.
Smarty puts too much logic into the template itself. To avoid
confusing or upsetting the web designer, the core template must look
as much like a regular HTML page as possible. That means no
strange looking iteration code and such. Instead, we'll use FastTemplate.
FastTemplate may not be as advanced and featureful as Smarty, but
its syntax is definitely better suited for this problem.
Let's look at a concrete example of what differentiates FastTemplate and
Smarty. Suppose we want to iterate through a set of database records,
presenting a list of products to sell online. With Smarty, this would be a very
simple task; we would just add something like the code below to the
template HTML file:
What's the big deal about this? It looks quite smooth. However,
when the web designer opens the HTML document containing this code in
Frontpage or Dreamweaver, what do you think the reaction is? "What
the heck is this?! Remove, remove, remove..." However, if we put this
logic into the PHP file instead, like FastTemplate does, the web
designer never has to see this logic, and the chance of getting a
valid template file back increases. With FastTemplate, you register
the iteration in the PHP file, but only mark it with a standard
HTML comment in the template:
<!--
BEGIN DYNAMIC BLOCK: products -->
<tr>
<td>{ProductName}</td>
<td>{ProductPrice}</td>
</tr>
<!--
END DYNAMIC BLOCK: products -->
FastTemplate uses the two comments to identify the dynamic block,
and then parses it according to the logic in the PHP file. This setup
is cleaner, as it doesn't mix up the logic with the
presentation. Also, the web designer won't need to bother about the
logic at all but can just open then template in any program, make the
necessary changes, and then upload it to the server (as long as the
comments stay intact, that is). Let's see how this would work in
reality.
Defining the Framework
To make it easier to create many web pages using this technique, we'll start
by defining a framework to include into other PHP files. This framework
consists of two files.
header.php will be included at the top of every PHP
file. It makes sure FastTemplate is initiated correctly. Then, by
using a couple of variables in the $_SERVER array, it
includes the correct template file and language file, and initiates
FastTemplate to use these files.
footer.php tells FastTemplate to parse the template
and language file into a human-readable result. It then prints this
result to the browser.
To use this framework, each PHP file will include header.php at
the top and footer.php at the end. Any logic for the web page goes
in between.
On line 2, we include the FastTemplate class, making it
available for use. Line 3 puts the name of this PHP file, with all dots
replaced by an underscore, in the variable $php_self_us. So, if
the name of your PHP script that has included header.php is
index.php, $php_self_us will contain
index_php. This variable is used on line 6 and line 9 to include
the correct language and template files.
In lines 4 and 5 we parse out the TLD (top level domain) for the current
server. Line 4 copies the last dot and everything after it from
$_SERVER['SERVER_NAME'] to the variable $tld. If your
server name is http://www.myserver.com/, the value of
$tld will be .com. Line 5 then uses
substr() to remove the leading dot of $tld.
Line 6 includes the correct language file for this request. If your document
root is /usr/local/apache/htdocs, the name of the PHP script is
index.php; and if the server name is
http://www.myserver.com/, then the complete path to and name of
the file included here will be
/usr/local/apache/htdocs/index_php_com.lang. This file should
define all text for the .com version (probably in English) of your
site in an array called $text. We'll examine that more closely a
little later.
Next, on line 7, we create a new FastTemplate object, using the document
root as the location of all template files. Line 8 assigns the texts defned in
the language to the FastTemplate object. In practice, this means FastTemplate
will be able to replace all text constants in the template file with the real
text. On line 9, we tell FastTemplate which template file to use. If the PHP
were named index.php, this call would search for a template file
called index_php.html.
footer.php is very simple. It ensures that the FastTemplate
instance was created correctly, parses the template defined in the last line of
header.php, then prints the result to the browser: