Skip to: Navigation | Content | Sidebar | Footer


Weblog Entry

Simple Templating

June 08, 2005

Simple static site templating with a CSS focus.

I use a very lightweight templating system of my own devising on this site that strikes me as something that might be of value to someone, somewhere. No database required, although you could certainly use one in conjunction with this method if you feel so inclined.

This is pretty basic stuff, so feel free to skip this one if you’re an old hand at server-side scripting. Then again, it sets up a lot of the CSS tricks I use around here, which may prove interesting even so.

Around 1998 or so, I maintained a semi-large site for a local ISP which grew pretty quickly, so templating was largely a matter of global find and replace. It was painful, to say the least, and the discovery of server-side includes, or SSI, was a rather important event for me back then.

If you’re not familiar, SSI was a method of allowing one file to include another. The practical upshot of which is that you can keep common site elements in one place (like, say, your site’s navigation). You need to change a navigation item? Change one file. Blam, you’re done. Convenient.

Thanks to SSI equivalents in server-side scripting languages like PHP and ASP, you can go further than just static files, too. Variables may be passed back and forth, and certain files may be included on some pages, ignored on others. It’s pretty powerful stuff.

My system on this site (which uses PHP, but once used ASP, so the concepts themselves are portable if not the code) consists of taking a comprehensive HTML file, and deciding what’s meat and what’s filler. The filler can easily be pulled out into a separate file, leaving only the meat within each individual page, which is as minimal as possible. On this site, I’ve determined that the page headers, sidebars, and footers are all filler. The sidebar and footer appear next to each other in the markup, so I’ve combined them into a single file.

So a typical page might look something like this:

<?php
	$pageTitle = "page title here";
	$pageClass = "secondLevel nosidebarPlease archives";
	include($_SERVER['DOCUMENT_ROOT'] . '/includes/header.php');
?>

	<h1>mezzoblue</h1>
	<div class="contentarea">
	  <p>This is where the page content would go.</p>
	</div>
	
<?php	
	include($_SERVER['DOCUMENT_ROOT'] . '/includes/footer.php');
?>

And that’s about it. No navigation, no sidebar, nothing but the content. Everything else is offloaded to external files. What might one of those files look like? Let’s open up header.php and see:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" id="www-mezzoblue-com">
<head profile="http://gmpg.org/xfn/11">
 <title>mezzoblue  §  <? echo $pageTitle; ?></title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

 <link rel="stylesheet" type="text/css" 
   title="mint" href="/css/wintermint.css" media="screen, projection" />
 <link rel="stylesheet" type="text/css" 
   title="mint" href="/css/wintermint-print.css" media="print" />
 <link rel="Shortcut Icon" type="image/ico" 
   href="http://www.mezzoblue.com/favicon.ico" />
 <link rel="alternate" type="application/rss+xml" 
   title="RSS" href="http://www.mezzoblue.com/rss/index.xml" />
</head>

<body class="<? echo $pageClass; ?>">

<div id="container">

<div id="intro">
 <div id="pageHeader">
  <h2><a href="/">mezzoblue</a></h2>
  <h3>Design, Typography, and the Web</h3>
  <h4><abbr title="International Standard Serial Number">ISSN</abbr> 
    1708-0789</h4>
 </div>

...

…and so on, right up to the line where the h1 would appear, were the HTML flattened. So everything you see up to that point when you view source, that’s all being generated by the header include file. There are some things going on in this included file that deserve a bit more explanation.

First of all, the page title:

<title>mezzoblue  §  <? echo $pageTitle; ?></title>

Within this line, there’s a snippet of inline PHP that simply ouputs the value of the $pageTitle variable where indicated in the markup. If you’ll recall the earlier example of a content page, there’s a line that sets this variable:

$pageTitle = "page title here";

This way, I can easily specify the title of any page within the page itself. Likewise, I’ve decided to give myself the ability to apply custom body classes for any page on the site:

<body class="<? echo $pageClass; ?>">

And again, the values for this script come directly from the page itself:

$pageClass = "secondLevel nosidebarPlease archives";

There are similar variables set up for the footer as well, but the last thing I’d like to touch on is the custom CSS method I use.

Because I find it handy to be able to import a style sheet on a whim, and because the head element is locked up inside header.php, I need to take a similar approach for these as well. Sure, I could just use the variable method above, but what if I want more than one CSS file? It has happened, so I’d better prepare for that contingency.

Arrays are a natural fit here. Stocking them is relatively easy; as with the other variables mentioned, this code just needs to land before header.php is included in the page:

<?
	$customCSS[0] = "/css/custom.css";
	$customCSS[1] = "/default.css";
	$customCSS[2] = "/css/articles/june-2005-1.css";
?>

And of course, something ultimately has to be done with those files in header.php:

<?
if ($customCSS) {
  $counted = count($customCSS);
  for ($i = 0; $i < $counted; $i++) {
   echo " <link rel=\"stylesheet\" type=\"text/css\" 
	title=\"mint\" href=\"" . $customCSS[$i] . "\" 
	media=\"screen, projection\" />\n";
  }
} ?>

Basically what this last snippet does is count the number of values in the array, and add a link for each one. Setting it up this way allows me to add as many CSS files as I need, without having to think about it.

This method of templating is just one way of doing it that happens to suit my needs rather well. You could also reverse the process and store your include files in one main site index file, which then loads content from a database; in that case, the individual files wouldn’t even have to exist if your server was capable of mod_rewriting. But we’ll leave that for another day.


June 08, 01h

Hello Dave, I would also like to recommend the smarty template engine to you. It’s easy, fast and unbelievably rich of functions, which normally take days to write them all from scratch.

The fun is, you mustn’t know these functions from the start. I’d say, somebody with your knowledge has the engine up and running in less than 20 minutes (including download) in a basic configuration - which most times is all you need.

Dividing php from html has (for a developer) the same purpose as dividing layout language (css) from html: it makes your code cleaner and easier to write/fix.

Geert says:
June 08, 01h

I thoroughly recommend this awesome light weight (about 20 lines!) php template class: http://www.massassi.com/php/articles/template_engines/

3
Scott Vonderberg says:
June 08, 01h

Does anyone have any good links/books on PHP for web designers without any programming knowledge? I would’ve loved to use some sort of templating or CMS on my last project but I don’t have any knowledge of PHP or Javascript, just XHTML/CSS. DW templates are pretty much a joke, I couldn’t even get them to work (wouldn’t recognize editable regions in the template) and they aren’t very flexible or slick anyway.

As a sidenote I’m a student with a job at a university where I handle interface design for a variety of on campus web services so I have experience designing around big, complicated and unwieldly Coldfusion apps. The gap in the growing CMS/templating world seems to be in small/scalable easy to use (hell an actual app with a GUI would be great) market for designers or complete laymen.

June 08, 01h

I use smarty on every project too. The nice thing is, you can let someone with little experience in php do some adjustement too the pages because it has a small syntax.
It also supports caching, which works fast!
And it really manages to seperate the layers…

db (mysql) - logic (php) - structure (html) - style (css)

And it’s more secure, like someone said before, you can’t run a tpl. You can even block people from retrieving a .tpl file.

Check it out! It’s great ;)

5
Keff says:
June 08, 01h

Thank you! Now I don’t feel like only man in the world whose RS is still filesystem-driven, without SQL.
So we’re two now :)))

June 08, 02h

I have a lengthy article on doing just this in PHP with lots of details. Many of the comments in previous posts here are addressed, such as having your include()ed code only return functions that actually output the sections of each document. It handles any doctype you want to use from HTML 4.01 transitional through XHTML 1.1 (which what I use).

Building Modular XHTML Web Pages with PHP
http://loadaveragezero.com/vnav/labs/PHP/

7
Tama says:
June 08, 03h

I’d second using:

error_reporting(E_ALL);

at the start of all your php pages.

All the projects I work on have strict error reporting turned on. It means you’ll get a warning message with the following code:

$output = “Testing 123”;
print $otput; // note the missing u

If you don’t have strict error reporting turned on you might end up tearing your hair out for hours wondering why php isn’t printing out anything (obviously this is a simple example!).

Dale says:
June 08, 04h

only put error_reporting on E_ALL for testing, never on a live site

for the templating, my method is

making a file .tpl with your index in it

<html>
usual header stuff
<body>
navigation
{content}
</body>
</html>

then file_get_contents() to get the template, put your content in $content

and echo str_replace(‘{content}’,$content,$template);

I used to use the given way, this ended up far more flexible.

the class i use is at
http://deadhit.com/bleh/Template.phps

June 08, 08h

Dave-

This is almost exactly the system I use on smaller sites for templating. I mean, down to the “T”. Great minds…. :)

kenrick says:
June 08, 08h

Well whatever suits your needs is really best, nothing worse than over coding a site.

I’ve been programming web sites with php for quite some time now, and realize though that there are benefits to rolling my own template system, its often better to just use a solution someone else has already created, is tested, and is in active development.

I used Smarty (smarty.php.net) for a bit, but really found it to be overkill, and not very flexible actually. The best template system Ive come across so far is just PHP itself! Now granted what Dave is doing more or less this concept, but if you really want to have some more flexibility in terms of handling your template files, its best to go with a template class like Savant (http://phpsavant.com/yawiki/) Paul M. Jones is an excellent developer, and this Savant template system is REALLY easy to use and comprehend. I use it in every single project. Its very simple to use, check out the quick start guide: http://phpsavant.com/yawiki/index.php?area=Savant2&page=StartExample

You can of course include other template files inside of your templates, run all available PHP functions etc. Its pretty cool, and really helps you separate the business logic from the display logic. (much easier to debug as well)

ak says:
June 08, 09h

i used to use this method as well, and it works, but i wanted something even more flexible.

i use xslt now as a sort of template engine. it’s not as easy of a thing to set up, but once it works, it offers so much flexibility. my whole site is built by one xsl file, and then another for rss.

Maciej says:
June 08, 09h

Why not using foreach(…) loop?

June 08, 09h

I do pretty much the same thing, for both static and dynamic sites. It’s a bit like doing a dynamic site without the database. The content is “imported” into a template in both cases.

June 08, 09h

heh. I use almost exactly that - except for the CSS import trick you described. I’ve been using SSI though, which doesn’t natively support arrays (that I know of) or for loops. Of course, now you’ve got me wondering how to make something like that work…

+1 for sharing it though. Many people will benefit, I’m sure.

Dave S. says:
June 08, 09h

“Why not using foreach(…) loop?”

Familiarity. Though I really should be.

June 08, 09h

Dave,

To save some time, do $var[]. It will automatically number them.

As for the foreach, you can do…

foreach ($customCSS as $c) {
print “<link rel="stylesheet" type="text/css" title="mint" href="”.$c.”" media="screen, projection" />\n”;
}

17
Johan says:
June 08, 09h

Would it be great to go further than this - the whole issue of creating template systems goes beyond this sort of templating articles? Did you considder using global variables and what about changing your vars? Is this done with a form? Would be nice to make a descent content management (php) system sthat is ultra light-weight like Limbo, a variation on mambo?

I think there is need of a real good article concerning making your own CMS?

It is important to know how to make a CMS surely if you are a webdesigner-webdeveloper.

June 08, 10h

Johan, if you visit http://www.intranetjournal.com/php-cms/ there is a nice series on creating a custom CMS using PHP. I’m sure with the knowledge from those articles, plus the information that Dave has given in this article, you could at least create a lightweight CMS for your own personal needs.

June 08, 10h

I know it probably is overkill for small projects, but I use smarty ( http://smarty.php.net/ ) all the time. It allows total seperation of php and html. Your code will get much more readable and maintainable.

As a bonus, you’ll get template-caching.

bofe says:
June 08, 10h

What’s the purpose of <h1>mezzoblue</h1> ?

Could that not be contained in header.php? Or put <h1><? echo $pageTitle; ?></h1> in header.php?

June 08, 10h

Instead of using…

if ($customCSS) {

}

Try

if (!empty($customCSS)) {

}

If your host has error reporting set to E_ALL then the way you do it will display a notice if the variable isn’t set. It’s a good idea to code so that your code doesn’t display notices when error reporting is set to E_ALL. On big applications this might actually speed processing time up.

Also instead of <? echo $pageClass; ?> you could use <?= $pageClass ?> which save a little typing and it’s simpler. Also, here again it would be good to using something like, <?= !empty($pageClass) ? $pageClass : ” ?> so you don’t display a notice if $pageClass isn’t set. This basically says if $pageClass isn’t empty or it’s not set then echo or print it’s value and if it’s not set then display nothing.

I also agree with Michael Simmons about the foreach loop. A foreach loop is much easier and simpler to read. In my templates I actually do them this way which is easier to under stand for the none PHP coder.

<? foreach ($customCSS as $c): ?>
<link rel=”stylesheet” type=”text/css” title=”mint” href=”<?= $c ?>” media=”screen, projection” />
<? endforeach ?>

I used to create all my HTML templates this way and I still do to a certain extent but now I use Savant2 (http://www.phpsavant.com/) which is a PHP Templating system that is very lightweight and acts on the same principles as what you described but forces a person to use good coding practices and separate your program logic from your display logic. You can continue to use PHP in your templates but you have to use them as objects. Savant2 has helped me to be a much better programmer and as a by product my code is a lot cleaner and more organized. This helps when working on bigger projects because all HTML are in templates what you can hand off to front end designers. However, in my case I do it all so it doesn’t matter as much but in theory that’s how it’s suppose to work.

June 08, 10h

This is almost identical to what I use as well. I’m also using some tricks from Doug Bowman http://www.stopdesign.com/present/2004/sydney/beauty/ to use different layouts by setting the id of the body tag.

Here’s what a template page looks like:

—————

<?php
$page[‘title’] = “Page Title”;
$page[‘section’] = “section”;
$page[‘description’] = “”;
$page[‘keywords’] = “”;
$page[‘template’] = “layout-sm”;
$page[‘head_content’] = ”;
?>
<?php include($_SERVER[‘DOCUMENT_ROOT’].”/inc/top.inc.php”); ?>

<h1>Page Title Goes Here</h1>

Content goes here

<?php include($_SERVER[‘DOCUMENT_ROOT’].”/inc/bottom.inc.php”); ?>

—————

$page[‘title’]
//Displays the page title inside the <title> tags

$page[‘section’]
//used for the class of the body tag, so css can be used to display the selected section in the navigation

$page[‘description’]
//Goes into the description meta tag

$page[‘keywords’]
//Goes into the keywords meta tag

$page[‘template’]
//used to set the id of the body tag (i.e., layout-sm, layout-smx, layout-m, etc.)

$page[‘head_content’]
//I use this in case I need to throw in a javascript include or some inline css inside of the head tags

June 08, 11h

It’s worth mentioning that for strictly best practice use of included files, your includes really shouldn’t actually output any HTML, they should just contain functions that return the HTML you need.

The rationale for this is that it prevents someone from hitting www.mezzoblue.com/includes/header.php directly - probably not a major issue for this sort of site, but it would be quite easy for inexperienced PHP developers to accidentally expose their database connection information or something equally sensitive through not protecting their include files from prying eyes.

June 08, 11h

I agree with Mathew that you risk security if you let them echo/print on their own. Especially if you try to use this method for something like user logins. They should be classed and called as functions as he mentioned.

Another side note: At least on my server, includes are significally slower than a query against MySQL. I’m guessing this comes from hard drive access being slower that hitting an already loaded database.

One more note, since this is the method I came from. If you don’t have PHP (scary thought), this same concept can be done using javascript fairly easily. I’m still using it (partially because it’s a dead site) at http://smrc.jrcorps.com/. The navigation is loaded by a very simple javascript call.

juque says:
June 08, 11h

Hi Dave, what about Smarty templates Engine [*]. I use it for three years with full satisfaction. With Smarty I can
to separate the code PHP of the HTML completely, I recommend it to you. My site is running with Smarty, please take a look.

[*] http://smarty.php.net/

June 08, 11h

Good morning,

thats so funny, that so many of us, developed a very similar system, without know the others doing like that.

Makes me happy.

:-)

I combine these technique with my simple CSS/PhP Navigation, that always shows up the actual site in the navigtion like the navigation on

www.steuerberater.at

thats the only special thing I have.

Greetings from Austria

Rene

27
Adam van den Hoven says:
June 08, 11h

SSI is a good way to do things if you have a realtively simple site. But if, like me, you have to maintain very large complex sites, it quickly becomes problematic, especially if you restructure your site. Its even more problematic if you want business users to edit content pages. And if you have many sites, each of which needs to have different layouts, and shares content between sites, you’re pooched.

If you can go to a Java based system, I would look at Sitemesh (http://www.opensymphony.com/sitemesh/ ). The basic idea is that you write your content as a normal stand along page. Sitemesh then takes that file splits out the title, the rest of the head and the body and decorates that with all your filler.

The advantages are many. First your content can stand alone as content and you can swap your decorators around as much as you like. Second, you can make sure that everything is well formed (rather than opening your body tag in the header and closing it in the footer….. I hate that).

Well worth the look

Sebastien says:
June 08, 11h

Hello,

If I have understand (i do not speak english very well), you do not use a database, is it right ?

So how do you make possible you search area ?

Thanks for the answer.

29
Masklinn says:
June 09, 01h

One thing that can be interresting if your templating system is so simple that the included files don’t actually hold any PHP to execute (aka if you include plain vanilla HTML and don’t want to use SSI): use the readfile() function, it has less security issues than include because it merely copies the content of the read file to the output, without trying to execute it or anything.

danbee says:
June 09, 04h

Just wanted to improve on Michael Simmons foreach loop a bit. Using echo instead of print is more efficient as it’s a PHP language clause rather than a function. Also single quotes prevent PHP parsing for variables in the string text and also removes the need to escape double quotes.

Lastly, you can echo as many things as you want by simply separating them with commas. So doing this instead of concatenating with a period will save the PHP parser some more work.

foreach ($customCSS as $c) {
echo ‘<link rel=”stylesheet” type=”text/css” title=”mint” href=”’, $c, ‘” media=”screen, projection” />\n’;
}

hink says:
June 09, 06h

Quite an interesting variation on dynamic style includes.

I use this little number to plop in stuff like browser or access-level specific stylesheets:

/* dynamically imports custom markup */
function StyleAppend($cssfile, $qualifier) {

global $hb_url; // main site url

if ($qualifier == 1) {

echo ‘<style type=”text/css”>’.”\n”;
echo ‘@import url(/’.$cssfile.’);’.”\n”;
echo ‘</style>’.”\n”;

}
}

calling it like so:

styleAppend(‘css/’.$hb_style.’-admin.css’, isTypeAdmin() );
styleAppend(‘css/’.$hb_style.’-opera.css’, preg_match(“/Opera/i”, $_SERVER[‘HTTP_USER_AGENT’]) );

A tad hard to follow out of context, and there is a dance to be done within the <style> element to be sure, but I thought it would be best to drop the comment-soup for this post.

Thanks. I sure do plan to work your array method into my style functions, its a keeper.

All the back and forth about the E_level is a bit silly, as any CMS worth its salt has a central settings file or DB table, in which error reporting can easily be toggled for debugging purposes - settings usually being the first thing included. ;)

32
Avik Das says:
June 09, 10h

My site (which is still in development), uses a similar templating system. However, I prefer to have all the “filler” in one file and actually include the content file based on the URI. I use mod_rewrite to get nice clean URIs, so I don’t get URIs like example.com/index.php?content.htm but still achieve the same effect.

I find this method easier because I have two files instead of three (one for all the filler, not one for the header and one for the footer), and the content file contains only content, no includes.

But the rest of the stuff, like the class attribute on the body element, and the dynamic page titles, I do the same. Good to see others thinking this way. It really does help usability.

dtamas says:
June 09, 11h

I use quite a similar, but more detailed php template system on my personal site.

Dante says:
June 09, 11h

Dave, yours is almost the exact same as mine too (great minds).

Instead of <?php echo $var ?> you can just write <?=$var?>.

June 09, 11h

Dave, thanks for this article. I was just in the process of devising this very type of thing for my websites and I have to say your solution is very lean and straight forward.

I love seeing other web developer’s logic when it comes to rolling in functionality. Each has a very singular style than can work or not work for anyone else. Thanks again!

June 09, 11h

This is good stuff. I use PHP to make templates a similar way, though I cut out a lot of the unnecessary code.

June 09, 12h

@Scott Vonderburg:
I’d recommend the Sams series but only the PHP specific books as the Apache, MySQL and PHP all in one book really isn’t as good. Use the 24hrs for an overview that covers most stuff and 21days for some extra detail and OO.

Available from all good bookshops :)

On topic: We used SSI in PHP on a uni project and it does make life a heck of a lot easier. Unfortunately we’re not taught to program defencively so thats gonna be really useful in future.

June 10, 01h

Hello,

As many others did, I’ve created something quite similar, with accessibility and W3C standards in mind. But I did it very open, and very modular.

Someone asked if something of the sort could be found, so I thought, that I could inform you of what I did.

I’m in the process of writing the minimum documentation, after which I’ll make the first public release under GPL. See here:
http://yves.gablin.club.fr/pc/www.php?doc=all

Almost forgot: I love this site of yours! I’ve read all articles since I’ve discovered it a month ago!

Yves.

(BTW: I’m not responsible for the trash that is after the < /body > :( on each page of my site…)

Daryl says:
June 10, 05h

I can’t say that the idea of header/footer files is a new and innovative thing… I’m not surprised most of us use it…

Dave, are you using this setup on the current mezzoblue?

Does it mean you have to manually add a link and description to your main page? And how about your friendly urls?

Do you manually create a new mod_rewrite rule?

J.Stam says:
June 10, 06h

I use a very similar system when building PHP sites, but it uses 2 files: the page itself (with content) and an HTML template file (header and footer combined).

Using the same idea you used to echo $pageTitle, on the HTML template file, echo a var for body content called $pageContent. On the page file, set that var just like you would the page title.

I like it because all of the HTML shell code is one file. PHP allows line breaks in vars (unlike ASP), so you can even maintain your HTML code structure. One downside is that all the content HTML on each page file must be set as a var which means you have to be careful of double quotes.

Kenneth says:
June 10, 08h

J.Stam, as far as I know, you *can* include line breaks in ASP vars.

varSomething = “this is the first line” &_
“but it continues here” &_
“and here”

June 10, 08h

Very similar methodology to what I use as well…

Re: Matthew Pennel in ref to what include files should include -

You server shouldn’t output any of the PHP as text, so you need not worry about ppl seeing your PHP cars, ie. db connnection string AFAIK, I’ve been using this methodology for years and have never seen a server output my PHP as text… unless I set the header to content-type: text/plain - but I digress, it is good practice to have everything output by the PHP, nothing in straight (X)HTML

RE: this being only for small sites -

You can still use this method to create a very large CMS template in one file… writing the headers and footers in functions which are called based on page type, which is stored in the database…


What’s nice is I now have a template of my templates, and modify little to create new sites….

June 10, 08h

In Reply to Michael (right above this).

The security issue isn’t always that if you open something like just the header file, you’ll get the connection strings. The issue is something much more interesting that tends to arrise when using this mindset to build a template engine.

The first thing that people like to do is change the extension to something like .inc. By default, .inc is not processed so actually do have the potential to get it back as plain text.

The second thing people like to do is make the content a included file/document based on some passed in variable. Again, if care isn’t taken, this gives the attacker the ability to pass in any file to get included from any file. If done right, you could probably find a way to include things that shouldn’t be.

The third thing that I’ve run into, again, only if care is not taken, is that if you have users or sessions (which you probably wouldn’t, but still possible on a small site), then you need to take care that your permissions flow nicely through the site.

These may all seem like common sense things, but because this is a pretty common template system that people come up with, they like to leave the little things out at the cost of their site being down a week later due to someone finding a bug.

This is the one reason I recommend Classing everything. It insures that your calling the functions you want from the include files… Not just letting them run rampant.

Then again, this is just my opinion.

dusoft says:
June 11, 05h

As somebody has mentioned above, I would advise to use single quotes as then it is easier to include HTML without the need for escaping double quotes.

I use similar templating system to yours, altough a bit more advanced.

stockfish says:
June 11, 05h

Hi,
this is nearly the same system that I normaly use in simple projects.
It´s effective and save time.

But when I need a solid groundwork for a project I use Smarty, too.

46
Tanner says:
June 12, 11h

This is very similar to how I used to template. Now, for whatever reason, I have one template file and a directory of “page” include files. Here is what a page source may look like

<?php

$title = “title”;
$menu = “menu1”;
$sidebar = “sidebar1”;
$content = “page/thispage.inc”;

include(‘template1.php’);

?>

The template file would put all the items in there correct place.

I don’t know why but I prefer this method.

Shaffick says:
June 13, 11h

I use a similar templating system as Dale [see above].

However, mine looks like this:

<html>
<head>
{title}
{meta}
{css}
{js}
</head>
<body>
{content}
{navigation}
{footer}
</body>
</html>

btw, i use css positioning for layouts, so the template above isnt entirely accurate..the divs are missing.

{meta} - for dynamic meta tags. people sometimes like different keywords for different sections of their sites

{js} - either empty of has some js tags in it

For every entry in my articles table [in the db], there is an extra column which points to which template to use for that page. Based on that, the page is displayed.

My parser is kinda similar to Dale’s except for a few extra functions [which i quite rarely use]

June 13, 12h

@ Sebastian

No on my website, Wordpress gives me the search box.

But when, I just build a static website, the I use this Template Syste.

I call it now STS (Simple Template System), sounds important ^^

Greetings

mike says:
June 14, 01h

Two of the coolest side effects of using this method is that (1) you get to use common page-specific elements in php functions and (2) You can refer to classes and IDs above those elements in the document tree.

For instance, if the body id is “products” then you change part of the consistent template (header or footer) to be specific for that page with a switch-case or an if-else. That way you can make a consistent template that changes based on the content without embedding it into each page, since it will be the same most of the time.

For the second one, let’s say you set a content id of “microwaves” as a PHP variable at the top and echo it as the ID of a content div. But oops, you want to have a banner specific to microwaves. No problem, you don’t have to rearrange divs or ids and change stylesheets, you can just refer to it with PHP, like IF $contentid==”microwave”.

Michael says:
June 16, 05h

I find it interesting that so many of us have been implementing ‘templates’ in this fashion without ever being aware of it. This is the first article I’ve run across about the technique. And timely too, I’d been thinking seriously lately about writing something up myself. Beat me to the punch!

June 22, 02h

Rolling your own custom template system is a good way to learn (everyone’s done it), but I just can’t use these on client sites (anymore)…

There are so many excellent existing template systems that can offer benefits like caching, widespread usage (read: well-tested), ease-of-install and updating (especially Flexy thanks to PEAR). Hell, just use Wordpress!

I’ve built several sites with slight variations of my home-brewed system (slowly fixing bugs and addign features here and there so every older site’s system is a little different and less bulletproof) and now I so wish I’d just used Smarty or whatever and put more time into improving the sites.

June 23, 10h

I use a system very similar to Dave for developing web sites. In any language, I just have three basic include files for the common areas: initialize everything in the <head> except the page title, the header/navigation, and footer.

However, I leave the DOCTYPE, <head>, and <body> tags on the individual pages, not as part of the include files. The major advantage is that the page can still validate locally without the include files – this is really helpful when using BBEdit’s or Homesite’s internal validation tools. And any unique meta data or custom styles can be directly added to <head> underneath the “initialize” include call.

So the basic, non-language specific page structure is:
<!DOCTYPE …
<html lang=”en”>
<head>
<title>…</title>
[include initialize.php]
</head>

<body>
[include header.php]
Lorem Ipsum…
[include footer.php]
</body>
</html>

Also most clients barely understand HTML, let alone ASP or PHP, so it feels easier to use a few include files and real simple HTML code whenever possible instead of setting numerous variables with a templating tool. This seems to avoid confusion and page errors (“I removed the semicolon and nothing loads!” -or- “I added my own <body> tag to every page because a book told me to and now it looks weird”).

June 27, 07h

As a side-note, while making my own framework, I’ve seen as an evidence, that the big difficulty lies in the separation between head and body.

If you want the page content to be sent “as soon as ready”, and not as a whole after being computed in memory, then the head has to be sent at a time when the body has not even begun being parsed yet. This leads to quite a few “casse-têtes” (puzzles?) for finding solutions.

Yves.

June 28, 10h

I did very much the same thing for a recent re-design of a friend’s site. Your loop to link to certain CSS files reminded me of a similar trick I did in the included header of that site.

I wanted to use SIFR on every page except the home page, but didn’t want to have a different header specific only to index.php. I ended up putting this into my included header:

<?php
if( basename($_SERVER[‘PHP_SELF’]) == ‘index.php’ ) {
// Do nothing
}
else {
print ‘<script type=”text/javascript” src=”assets/sifr/sifr.js”></script>’;
}
?>

Probably not the most elegant solution, but if you only need to worry about an exception on one page it gets the job done.

@ Matthew Pennell: Wasn’t aware of the security issues surrounding PHP includes. I’ll have to look into that further. Thanks for the tip.

Will says:
June 30, 01h

Well, I dont know jack about any of this so thanks a lot Dave. I actually just just just picked up my first book on PHP - the timing on your article couldn’t have been better.

As always, really clearly written. I even understood it! Actually, would you do me a favor and just ignore any other responsibilities/friends/earning a living and just blog on PHP for the next few months? Thanks. Yeah, and come in over the weekend? That’d be great. Thanks.

Will

56
Richard says:
July 03, 01h

Can you explain how your method of including css files copes with print stylesheets.

July 09, 06h

This is really awesome. I’m going to implement it with ASP on some of my sites. I just have to figure out how to do the array in ASP.

58
ras says:
July 10, 02h

Great article indeed, what would be really great if you could make the files available for download 8o)

Ras

59
Mihael Konjević // retro says:
July 13, 09h

For sites I develop, I use http://www.tinybutstrong.com template engine, and I must say that it’s one of the best. I’ve most of the template engines available, because I wanted to have solution that will fit all my needs, and this one is really great, yet preety small and simple.

Tim says:
December 19, 15h

I haven’t understand, do you use database, if yes, how do you connect it to script?

Dimon says:
December 28, 08h

One thing that can be interresting if your templating system is so simple that the included files don’t actually hold any PHP to execute (aka if you include plain vanilla HTML and don’t want to use SSI): use the readfile() function, it has less security issues than include because it merely copies the content of the read file to the output, without trying to execute it or anything.