How do they work?
Here's a very basic example:
Welcome to BlahdeBlah Ltd. Please fill out the following form to signup for our regular email newsletter.
As you can see, it is all plain text - not a <?php or a ?> in sight. Instead, keywords are used, encased in square brackets in order to differentiate them from plain text, to represent where PHP code should go. The designer sprinkles the special keywords into their layout wherever they want pre-written functionality to appear, and their job is done - no programming required.
To turn the designer-produced keyword/layout mix into a useable page, a simple parser would have to be written that locates each keyword and converts it to the appropriate PHP code. So, [HEADER] is turned into the full page header for the site, [NEWSLETTERSIGNUP] into a form, etc.
Let's take a look at the code necessary to convert this into a page that can be shown to visitors. Naturally, we cannot let people link directly to the HTML page because it will not be parsed by PHP, so we need to write a master script to handle all page requests.
Here is the code for an example master script; save it as default.php.
if (!$page) $page = 'default.html';
$content = file_get_contents($page);
$content = str_replace('[HEADER]', '<?php include \'header.php\'; ?>', $content);
$content = str_replace('[FOOTER]', '<?php include \'footer.php\'; ?>', $content);
$content = str_replace('[NEWSLETTERSIGNUP]', '<?php include \'nlsignup.php\'; ?>', $content);
eval('?>' . $content);
We then load in the page that was requested, using file_get_contents(). I recommend you do not put the content pages in the same directory as the template code itself. There is no harm keeping all the files, except default.php, outside the public_html directory entirely, in fact I would recommend it - it's the easiest way to ensure hackers aren't able to dig up more information than you want. On that note, you may want to filter the value of $page so that people cannot provide a value like "../../../etc/passwd" - this is a very common trick, and I have seen it work on many sites that use the include() function. The simplest way to solve this is simply to reject $page if it does not start with one directory above your root public HTML folder, e.g. "/home/paul/www/".
Back to the parsing script, it continues on by replacing all our template keywords with PHP include() s leading to our pre-written code. For extra speed, you can just directly write the code itself rather than calling include(), but space is at a premium here, so include() is preferable. Whilst include() is a touch slower than putting the code directly into the page, it keeps the master script easy to read, which is probably a bigger advantage in the long run.
Finally, we call the eval() function, passing in our newly-parsed content prefixed with a '?>'. eval() executes PHP code as if it were a script by itself, which is immensely helpful because it allows you to create your PHP code dynamically at run-time, as we do here. The reason we prefix our content with ?> is because eval() is expecting PHP code. We need to start with a "drop out of PHP mode" command because it is very unlikely that our non-technical web designer will have started their content with PHP code, or, if they need to, they should at least start their script with <?. The worst case is that they start with a template command, which means the first thing eval() will encounter will be the ?> we prefixed to the content followed by the <? of one of our includes - hardly anything to worry about.
So, with just six lines of code, we have the most basic templating system ready. Of course, you would still need to go ahead and write all the individual templates (e.g.: HEADER, FOOTER, etc), but those can be added over time - our non-technical web designers can start using the system with just a couple of templates, with more being added later.
Next chapter: When not to use templates >>
Previous chapter: Templates ABC
Home: Table of Contents