A simple PHP HTML/CSS templating system (REDUX)

It is beyond silly to repeatedly copy and paste the same HTML into the top and bottom of every HTML file that you create. That’s why god invented include() but, the humble header/footer HTML include file needs to be extended slightly – that is, unless you want all your pages to have the same title/meta description/CSS files etc.

A while ago I wrote about my PHP-based HTML template system. It has since been rewritten to make better use of PHP5’s object oriented approach and here it is:

My template structure is as follows

  • a basic HTML page – aka the View in the Model-View-Controller (MVC) approach
  • a header HTML includes file – /templates/header.php
  • a footer HTML include files – /templates/footer.php
  • a simple template class – /class/template.class.php

The page (view)

  1. <?php
  2. require_once($_SERVER['DOCUMENT_ROOT'].'/class/template.class.php');
  3. // Initialise template object
  4. $objTemplate = new Template();
  5. // SEO
  6. $objTemplate->setTitle($objTemplate->site_name);
  7. $objTemplate->setDescription("This is the page's meta description.");
  8. // CSS
  9. $objTemplate->setStyle(array('home','forms'));
  10. $objTemplate->setExtraStyle('p.example{color:red;}');
  11. // JavaScript
  12. $objTemplate->setBehaviour(array('jquery'));
  13. $objTemplate->setExtraBehaviour("$(document).ready(function(){$('#paragraph').addClass('example');});");
  14. // Header HTML file
  15. include($objTemplate->header_file);
  16. ?>
  17. <p id="paragraph">Page content goes here</p>
  18. <?php include($objTemplate->footer_file); ?>

Download page file

The idea here is to minimise the amount of repetitive code.

This page could be index.php, about.php or anything. If you’re using PHP’s autoload function you can skip the require_once($_SERVER['DOCUMENT_ROOT'].'/class/template.class.php');
line. You may have a universal initialisation file/class that is automatically included at the top of each page/view and in that you could add the line $objTemplate = new Template(); which would reduce your code size again.

The header

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml"<?=$objTemplate->language?>>
  3. <head>
  4. <?=$objTemplate->charset?>
  5. <title><?=$objTemplate->title?></title>
  6. <?=$objTemplate->description?>
  7. <?=$objTemplate->style?>
  8. <?=$objTemplate->robots?>
  9. <link rel="Shortcut Icon" href="/favicon.ico" type="image/x-icon" />
  10. </head>
  11. <body id="<?=$objTemplate->body_id?>">

Download header file

If this were a flat include file, it would be difficult to alter the <title> and other values in this file. In this approach, it is very easy to set the correct values via the page/view, meaning this file never needs touching by your pesky front-end developers again – in theory.

The footer

  1. <div id="footer">
  2. <div id="copyright">
  3. &copy; <?=date('Y')?> <?=$objTemplate->site_name?>
  4. </div>
  5. </div>
  6. <?=$objTemplate->behaviour?>
  7. </body>
  8. </html>

Download footer file

The class

  1. <?php
  2.  
  3. class Template{
  4.  
  5. public $site_name;
  6.  
  7. public function __construct(){
  8. $this->site_name = 'Amazing website';
  9. $this->setTitle();
  10. }
  11.  
  12. public function setTitle($value = false){
  13. $this->title = ($value) ? $value : $this->site_name;
  14. }
  15.  
  16. }
  17.  
  18.  
  19. ?>

For brevity’s sake, the majority template class code has been omitted from above, leaving only this simple example of how the title is created.

Download the (full) template class file

OO advantages

In my first template code, I used a function-based (procedural) approach with lots of separate includes file for elements such as CSS. It was good but this approach has a few distinct advantages.

  • It is hopefully easier to read and follow for someone with less PHP experience
  • You can create a subclass for sections in your site that need a different appearance e.g. and set a different header file to be included.
  • All the options could excluded e.g. setTitle(), setStyle() and the page would still work great.

Disclaimer

This template is quite simplistic, and I use it mostyly when creating HTML/CSS templates for people from Photoshop designs. In more demanding scenarios, I have a more complex template class which checks whether I’m in production mode, local mode, test mode, etc and acts accordingly. This may mean putting all the CSS and/or JavaScript into one file and compressing the filesize. It may mean adding a Google Analytics script at the bottom of the page on the live server.

Another question, you may be asking is, ‘Why not just use Smarty or similar?‘ Well the answer to that, is because I think they make the situation more complicated than it needs to be. My solution saves me time and when I pass my HTML templates onto the development team, it often saves them time too.

What do you think?

Is the code ugly? Is your PHP HTML/CSS templating system much better? Do you prefer a smarty approach?

I’d like to know.

16 responses to “A simple PHP HTML/CSS templating system (REDUX)”

  1. Good to see. One extra improvement could be make your setStyle expect an associative array so that you could specify the CSS media.

    Also… where are your getters?

  2. @Andy, that’s a good idea about the associative array. I should also modify the code so it expects a string as well because I can imagine a lot of people not thinking to use an array when specifying just one CSS file and causing an error.

  3. Good idea, I implemented something similar to this on a site I am developing a few days ago… Not sure it is needed in all cases though.

  4. That’s awesome. I’ve used a crude method by declaring $title before the include and echo’ing the $title in the tag, but this is much more sophisticated, especially for pages that need included javascript.

  5. @will: Sure there will be times when this is overkill but I think they are few and far between. This is just as useful and timesaving on a website with 5 pages as it is on a site with 50.

    @Jimmi: I had a look, I like the caching feature but I think there’s too much going on in that class without enough benefit.

    @Niobe: I started very similarly to you and only improved my technique when projects warranted it.

  6. Very simple and gets the job done. Good work.

    About choosing a media type for the css, I would do this:

    $objTemplate->setStyle(array(‘home’,’forms’), ‘screen’);
    $objTemplate->setStyle(‘print’, ‘print’);

  7. @louis w: I like the way you think. The current class does allow a (rather clunky) way around with the setExtraStyle method e.g:

    $objTemplate->setExtraStyle(‘@import url(“/style/print.css”) print;’);

    or

    $objTemplate->setExtraStyle(‘@media print{ css{rule: goes-here;} }’);

    but your way is better!

  8. Nice work. And clean, notation as well, habit I’ve got to get into. Have you thought of using php DOM (compiled with PHP 5), I’m building a similar tmeplate system at the moment using it, which lets you insert html elements on the fly (just in case you missed something).
    Can send you a copy of the class if you want it.
    Keep up the good work.
    D

  9. This looks great. I have been searching for a good template to build my website (v2) on. I have tow questions:

    1. The code seems to work fine if I comment out –> $objTemplate->setExtraBehaviour(“$(document).ready(function(){$(‘#paragraph”).addClass(‘example’);});”); Any idea why?

    2. *Noob Alert* But why not just include the footer file and header file? Why go through the trouble of using OOP for a template? Like I said, noob, but I have seen it used over and over and never quite understood the benefit.

    Thanks for your time and contribution! -SP

  10. @Sean-Paul:

    1: There is a mistake in the code, it should be
    $objTemplate->setExtraBehaviour("$(document).ready(function(){$('#paragraph').addClass('example');});"); note the after #paragraph, I’ll fix the example.

    2: You can just include the header and the footer file and that will work great in most cases. A lot of people even include the Doctype at the top of their pages instead of putting that in a header file. The beauty of this approach is that you can suddenly switch which header file to include based upon any number of factors.

    I’ll be honest and say this OOP approach’s advantages over a procedural approach can be difficult to see and that’s because they’re not that big. The code looks nicer and OOP is flavour of the day. Using this template, you’ll hoping find updating/creating basic websites much quicker.

  11. Good to see that more ppl finally start using this habit of dividing pages into included parts.

    But it was certainly not God that invented it

    It’s a good point mentioning it again. but the Idea is already SO OLD

  12. @Vinny: I’m confused as to what your point of view is. You seem both annoyed that this is an old topic yet pleased that it is being brought up again.