A complete template system

Where are we?

You know how to use require statements. You know how to use variables to fix broken paths.

Now let’s put it all together. Let’s make a site that has a complete PHP templating system.

This lesson’s goals

By the end of this lesson, you should:

  • Review a site with layout, images, and animated navigation.
  • See how to create a complete PHP template system for this site.
  • Understand the productivity wins this gives us.

Site review

Let’s remake the dog site we looked at a couple of lessons ago. Here is its overall structure:

Site structure

Figure 1. Site structure

There are two sections in the site: dog profiles and articles. The profiles section has profiles of several dogs. The articles section has articles on dog issues.

Here is the home page of the new site.

Home page

Figure 2. Home page

Note that the buttons on the nav bar match the site structure in Figure 1.

The dogs link on the home page, and the dogs button in the nav bar, link to the main page of the dogs section of the site. Here it is:

Main page of the dogs section

Figure 3. Main page of the dogs section

Each link shows a page about a dog. Here’s a sample:

Dog profile

Figure 4. Dog profile

Each dog profile has a photo of the dog.

The other section of the site in Figure 1 is the articles section. Here is its main page:

Main page of the articles section

Figure 5. Main page of the articles section

The page has links to each article. Here’s one of them.

An article

Figure 6. An article

There is one other page: the contact form. A link to it is in the footer of every page. Here it is:

Contact page

Figure 7. Contact page

You can try the site yourself. You can also download the site.

Page layout

Each page has the same layout:

Page layout

Figure 8. Page layout

There are four regions on the page: top, left, center, and bottom. There is no right region in this layout.

The top region has a header. It contains two images (the logo and header image), and some text (a site subtitle). The content of the header – the images and text – is the same on every page.

The left region has a nav bar that is the same on every page. It has three images. The images switch when the mouse hovers over them:

Mouse hover effect

Figure 9. Mouse hover effect

The bottom region has a footer that is the same on every page. It contains some text, and a link to the contact page.

The center region has the main content for the page. It is different for each page.

HTML components

Let’s open up the HTML for a page, and see how it is organized.

HTML organization

Figure 10. HTML organization

Inside the body tag are the four regions. Each has each own div. The colors match the ones in Figure 8.

Figure 10 uses code adapted from the liquid layout in the page layout lesson. The right region was removed, and widths, margins, and padding adjusted.

There’s some more HTML at the start and end of the page. The code at the start gives meta data like title, loads CSS and JavaScript files, and includes any page-specific CSS and JavaScript. The code at the end of the page just closes the body and html tags, although it might do more on other sites.

Remember the PHP!

The HTML for a page is not stored in one file. A key point to remember is that the HTML in Figure 10 is assembled by PHP code.

The HTML is broken up into pieces. Most of the pieces are shared by all pages. The header, for example, is the same across the site (apart from adjusting file paths). The only thing that is completely different for each page is the content.

That’s what gives us the Big Win. There will be one file containing the HTML for the header, no matter how many pages are on the site. 100 pages? One header file. 10,000 pages? One header file.

Change that one file, and every page on the site changes. All 100. Or 10,000. A big productivity win.

Where are we? You’ve seen:

Let’s see what the site’s directory tree looks like.

File organization

Here it is:

Site directory tree

Figure 11. Site directory tree

The root directory of the site just has two files: index.php and contact.php. All of the other files are in directories.

There is a directory for each major part of the site in Figure 1.

Why create a directory for each part of the site? This is another example of how Webers think about productivity. Suppose a user sends this email:

Email about spelling error

Figure 12. Email about spelling error

We want to be able to fix that error quickly and easily. Notice how easy it is to find the file with the error. All the articles are in the articles directory, so go there. The names of the files match the titles of the articles, so we open the file playing-with-dogs.php.

On the other hand, suppose we’d put all of the files in one directory, and named them things like file17.php. It would be harder to find the file with the spelling error.

So the organization in Figure 11 gives us another productivity win. W00f!

OK, back to the files. Here is the tree again.

Site directory tree

Figure 11 (again). Site directory tree

All of the shared files are in library. The file dogsite.css is a site-wide CSS file, with the colors, fonts, page layout style rules, etc. dogsite.js has the JavaScript code for the nav bar image switching.

The .inc files contain the HTML pieces for each page. There’s one file for each chunk in Figure 10:

  • The page start HTML (start_page.inc)
  • The top region HTML (header.inc)
  • The left region HTML (left_nav.inc)
  • The bottom region HTML (footer.inc)
  • The page end HTML (end_page.inc).

We’ll look at the code for each one in a moment.

The rest of the files in library are images for the header and the nav buttons.

Inside the PHP page

Now let’s open up /index.php (the home page), and look at the PHP. Here is the entire code:

//Path from this page to the site root.
$path_to_root = '.';
//Title of this page.
$page_title = 'Welcome';
require $path_to_root . '/library/start_page.inc';
require $path_to_root . '/library/header.inc';
require $path_to_root . '/library/left_nav.inc';
<div id="center_region">
  <p>See some <a href="dog-profiles/index.php">dogs</a>.</p>
  <p>Read an <a href="articles/index.php">article</a>.</p>
require $path_to_root . '/library/footer.inc';
require $path_to_root . '/library/end_page.inc';

Figure 13. PHP for /index.php (the home page)

Line 2 is a comment. Comments begin with //.

Line 3 sets the variable $path_to_root. It contains the path from this file to the site root. /index.php is already at the root, so the variable is set to '.', which means “the current directory.”

Line 5 sets the variable $page_title to, well, the page title. This is used in the title tag, as we’ll see.

Lines 6 to 9 insert chunks of HTML. start_page.inc (line 6) goes down to the body tag. header.inc (line 7) is the page header. left_nav.inc (line 8) is the nav bar.

Line 9 ends the PHP code. Regular HTML follows.

Lines 10 to 14 are the main content of the page, in the center region. This is what varies the most across the pages of the site.

Line 15 starts PHP mode again. Line 16 inserts footer.inc, with the HTML for the page footer. Line 17 inserts end_page.inc, with the HTML to close the body and html tags.

Let’s have a look at /dog-profiles/renata.php, the page showing Renata’s profile. Here’s what it looks like in a browser:

Dog profile

Figure 4 (again). Dog profile

Here’s the code.

//Path from this page to the site root.
$path_to_root = '..';
//Title of this page.
$page_title = 'Renata';
require $path_to_root . '/library/start_page.inc';
require $path_to_root . '/library/header.inc';
require $path_to_root . '/library/left_nav.inc';
<div id="center_region">
  <h1>Dog profile: Renata</h1>
  <p>Here is Renata.</p>
  <p><img src="renata.jpg" alt="Renata"></p>   
  <p><a href="index.php">Back to the dog list</a></p>
require $path_to_root . '/library/footer.inc';
require $path_to_root . '/library/end_page.inc';

Figure 14. PHP for /dog-profiles/renata.php

Most of it is the same as the code for /index.php, in Figure 13. Let’s look at the differences.

Line 3 has the path to the root. /dog-profiles/renata.php is in a subdirectory, so its path is “..”.

Line 5 has the page title. It is different, of course.

The content for the center region starts at line 10. That’s completely different from page to page, of course.

And that’s it. Those are the only differences.

Notice how easy it is to create a new page. Copy one of the existing pages, change the root path and title, and add the unique content. The header, footer, and nav bar are all set up.

This is another productivity gain. Creating new pages just got a lot simpler.

Let’s look inside the included files.

Here’s start_page.inc, the HTML up to the body tag (see Figure 10).

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title><?php print $page_title; ?> | The Dog Site</title>
    <link rel="stylesheet" type="text/css" href="<?php print $path_to_root; ?>/library/dogsite.css">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
    <script type="text/javascript">
      var path_to_root = '<?php print $path_to_root; ?>';
    <script type="text/javascript" src="<?php print $path_to_root; ?>/library/dogsite.js"></script>

Figure 15. start_page.inc

The page title is added in line 5. The root path is used in lines 6, 9, and 11. The rest is just plain HTML.

Here’s the code for header.inc.

<div id="top_region">
  <div id="logo_images">
    <img src="<?php print $path_to_root; ?>/library/logo.png" alt="Logo">
    <img alt="The Dog Site" src="<?php print $path_to_root; ?>/library/header.png">
  <div id="subtitle">Bringing you happiness since last week</div>

Figure 16. header.inc

The root path is used on lines 3 and 4, to get the right paths to the image files.

Here is left_nav.inc.

<div id="left_region">
  <ul class="vertical_menu">
      <a href="<?php print $path_to_root; ?>/index.php">
        <img id="home_button" src="<?php print $path_to_root; ?>/library/home_up.png" alt="Home">
      <a href="<?php print $path_to_root; ?>/dog-profiles/index.php">
        <img id="dogs_button" src="<?php print $path_to_root; ?>/library/dogs_up.png" alt="Dogs">
      <a href="<?php print $path_to_root; ?>/articles/index.php">
        <img id="articles_button" src="<?php print $path_to_root; ?>/library/articles_up.png" alt="Articles">

Figure 17. left_nav.inc

Each link and image needs to be adjusted for the root path.

Here’s footer.inc.

<div id="bottom_region">
  <p>© 2010 Nobody at all  
  |  <a href="<?php print $path_to_root; ?>/contact.php">Contact</a></p>

Figure 18. footer.inc

The path to the contact page needs the root path. Nothing else changes.


Hey, wait a minute.


What’s up?


Well, I’m just thinking. This seems awfully complex. Is it worth the effort?


Yes, I agree. I’m not sure I’ll like PHP.


Good point. Let’s talk about that a bit.

The source of complexity

Have a look at the directory tree again.

Site directory tree

Figure 11 (again). Site directory tree

There are lots of pieces here. Look at the library directory. There are fifteen files in there! Ack!

But let’s look more closely. Six of the files are button images. Another two are images for the header region. Nothing to do with PHP there, just regular images.

The files dogsite.css and dogsite.js have nothing to do with PHP either. They’re just regular things we saw in ClientCore.

What about the five .inc files? They are mostly plain HTML. There is only one PHP statement in them: print. As in:

<?php print $path_to_root; ?>

In fact, there is only one other type of PHP statement in the entire site. That’s require, as in:

require $path_to_root . '/library/start_page.inc';

The complexity comes not from the PHP. It comes from the underlying complexity of HTML, CSS, and JavaScript itself.

Web sites are complex. There is no doubt about it. That’s why people pay other people to create them.

The complexity comes not from the fact that any one thing is complex. But even in a small site, there are dozens of things to get right. Each of those small things combines to make a complex whole.

Don’t feel bad if this seems messy to you. It is messy. There’s a lot going on. But it’s your mastery of this that will make you a valuable employee, consultant, or whatever.

And one more thing about complexity. We added the PHP not to make the Web site look better. We added it to make it easier to change. Not only do we have the complexity of HTML, CSS, JavaScript, jQuery, and PHP. We have the complexity of work processes as well.

Ack! It’s enough to drive you to catnip.

The productivity wins

There are some big productivity wins here. Let’s review.

Win: new pages are easy to create

We want a new page, like a new article. We just copy /index.html (or another of the PHP files), change the root path and the title, and add the new content. We just work on what is unique on that new page. We don’t even have to think about the header, nav bar, etc.

Win: making changes in individual pages

Remember the email we looked at earlier, the one that told us about the spelling error? We could find the file to change very easily, because:

  • The directory tree matches the structure of the site, and
  • The file names match the page titles.

This has nothing to do with PHP. It’s just another example of how Webers think. Organize now to reduce problems later.

Big win: making site-wide changes

We can change the entire site by changing one file. For example, let’s say we wanted to add a new section to the site, for products. We add a new button to left_nav.inc, and every page in the site has the new button!

This is a Big Win. Your employer or client will be glad they hired you, because you give good value for money.


In this lesson, you:

  • Reviewed a site with layout, images, and animated navigation.
  • Saw how to create a complete PHP template system for this site.
  • Read about the productivity wins this gives us.

What now?

Time to do some more exercises.