<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>How this site works</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
<!--
-->
</style>
</head>
<body>
<p style="color:#FFF;font-weight:bold;background:#FFC000;padding:1em 1ex;text-shadow:0 0 3px #000">This article was last updated Monday, 13 December 2004. View a newer version at my site, <a style="color:inherit" href="http://hardanswers.net/template-based-site">hardanswers.net/template-based-site</a></p>
<h1>Templates</h1> 
<p>Creating static pages for a site works well when the site is small, but gets
    very cumbersome as the site becomes bigger – a site-wide change has to be performed
    in every single file on the site, taking a lot of time and effort. The usual
    way to overcome this is by the use of templates. A template is a single page
    or style that is applied to a whole site, meaning that most site-wide changes
    can be done by simply editing the template, rather than every file in the site
    – saving a lot of time and effort. </p> 
<p>The system I’ve used allows me to store the content in plain <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> files,
    easily created and maintained by anyone using any standard <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> editor,
    such as Dreamweaver. This makes it particularly easy to deploy new content and
    modify existing content. </p> 
<p>The basic logic is that I have a single file that applies all the site-wide
    features, such as common headers, footers and styles, and the individual page’s
    content is included into this file and displayed to the user. </p> 
<p>The basic concept<br /> 
    <textarea name="textarea" cols="82" rows="5" readonly="readonly" title="">
Consistent Header

Individual Page Contents

Consistent Footer
</textarea> 
</p> 
<p>However, because the individual pages are stored as complete <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> files,
    and the resulting output page must also be a complete <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> file,
    it is not possible to simply include the entire individual page into the
    template. The result would look something like this, which is not a valid <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> page. </p> 
<p>Invalid <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> page<br /> 
    <textarea name="textarea" cols="82" rows="14" readonly="readonly" title="">
&lt;html>
&lt;head>
    &lt;title>Page Title&lt;/title>
&lt;/head>
&lt;body>
    &lt;html>
    &lt;head>
        &lt;title>Page Title&lt;/title>
    &lt;/head>
    &lt;body>
        &lt;p>Individual Page Body&lt;/p>
    &lt;/body>
&lt;/body>
&lt;/html>
</textarea> 
</p> 
<p>To overcome this problem, I have a function that accepts a file name and a
    tag name, and returns the contents of that tag from the given file. </p> 
<p>Parse tag function<br /> 
    <textarea name="textarea" cols="82" rows="17" readonly="readonly" title="">
// Parse file for tags
    // parse the given $file for the given $tag and return any contents within
    // that tag
    function include_tag($tag, $file)
    {
        // read contents of file into $data
        $data = file_get_contents($file);

        // match the &lt;$tag blah="blah">contents&lt;/$tag>
        preg_match( 
            "/&lt;$tag.*>(.+)&lt;\/$tag>/sU", 
            $data, 
            $matches 
        );
        // eval the contents from above match
        eval('?>'.$matches[1]); // &lt;?
    } // end include_tag
</textarea> 
</p> 
<p>I can now include just the body tag from each individual page, as the content
    of my template. A simple template such as this will now produce a valid <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> page. </p> 
<p>Simple template<br /> 
    <textarea name="textarea" cols="82" rows="16" readonly="readonly" title="">
&lt;?php
    // Here we would have code that sets $file to the appropriate file name
    $file = 'included_page.html';
?>
&lt;html>
&lt;head>
    &lt;title>&lt;?php include_tag('title', $file) ?>&lt;/title>
&lt;/head>
&lt;body>
&lt;?php
    include('header.inc');
    include_tag('body', $file);
    include('footer.inc');
?>
&lt;/body>
&lt;/html>
</textarea> 
</p> 
<p>Valid <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> page<br /> 
    <textarea name="textarea" cols="82" rows="10" readonly="readonly" title="">
&lt;html>
&lt;head>
    &lt;title>Included Page Title&lt;/title>
&lt;/head>
&lt;body>
&lt;p>Header things from header.inc are here&lt;/p>
&lt;p>The content of the &lt;body> tag of included_file.html is here&lt;/p>
&lt;p>Footer things from footer.inc are here&lt;/p>
&lt;/body>
&lt;/html>
</textarea> 
</p> 
<p>With a bit more code, you have yourself a simple, functional template. </p> 
<p>Simple, semi-functional template<br /> 
    <textarea cols="82" rows="23" readonly="readonly" title="mod_rewrite code">
&lt;html>
&lt;head>
&lt;?php
    // set $file to the ?file part of the URI
    // http://domain.com/?file=file-name
    $file = $_GET[file];

    // include the parse tag function
    include('parse_tag_function.inc');

    // print the page title
    print '&lt;title>';
    include_tag('title', $file);
    print '&lt;/title>';
?>
&lt;/head>
&lt;body>
&lt;?php
    include('header.inc);
    include_tag('body', $file);
    include('footer.inc);
?>
&lt;/body>
</textarea> 
</p> 
<p>Care must always be taken to ensure that anything able to be externally passed
    into a file isn&#8217;t malicious. A simple function such as this attempts to
    find <acronym title="PHP Hypertext Preprocessor (server-side scripting language)">PHP</acronym> and <acronym title="Hyper Text Markup Language">HTML</acronym> files,
    and returns a default <acronym title="PHP Hypertext Preprocessor (server-side scripting language)">PHP</acronym> file
    if none are found. This can prevent anyone attempting to access anything unusual.</p> 
<p> 
    <textarea cols="82" rows="7" readonly="readonly" title="file verification code">
function verify_file($file) {
    switch(true) {
        case file_exists($file.'.php'): return $file.'.php';
        case file_exists($file.'.html'): return $file.'.html';
        default: return 'default.php';
    }
}</textarea> 
</p> 
<p>Individual files are now stored as <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> or <acronym title="eXtensible Markup Language">XML</acronym>. <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> files
    are parsed for their body, style and title tags and these tags are then included
    into the resulting output. This allows a simple template system where the content
    can be created with any <acronym title="Extensible Hypertext Markup Language">XHTML</acronym> capable
    editor, and I have found this to be the simplest way of creating a consistent
    and easily updateable style across a site.</p> 
<p>There are several advantages and a few disadvantages to this approach.</p> 
<p>Disadvantages include:</p> 
<ul> 
    <li>Slightly more processing is required to parse a file, rather than serving
        straight <acronym title="Hyper Text Markup Language">HTML</acronym></li> 
    <li>Initial design is more complex</li> 
</ul> 
<p> Advantages include:</p> 
<ul> 
    <li>Easily updateable</li> 
    <li>Easy to maintain</li> 
    <li>Consistent across an entire site</li> 
    <li>Content generation possible with the majority of &#8220;webpage&#8221; <acronym title="Hyper Text Markup Language">HTML</acronym> editors,
        as well as by hand</li> 
    <li>Foreign content assumes a consistent style after parsing</li> 
</ul> 
<p>For further information on: </p> 
<ul> 
    <li>eval(), see <a href="http://www.php.net/manual/en/function.eval.php" title="External Site | www.php.net">http://www.php.net/manual/en/function.eval.php</a></li> 
    <li>include(), see <a href="http://www.php.net/manual/en/function.include.php" title="External Site | www.php.net">http://www.php.net/manual/en/function.include.php</a></li> 
    <li>file_get_contents, see <a href="http://www.php.net/manual/en/function.file-get-contents.php" title="External Site | www.php.net">http://www.php.net/manual/en/function.file-get-contents.php</a></li> 
    <li>preg_match, see <a href="http://www.php.net/manual/en/function.preg-match.php" title="External Site | www.php.net">http://www.php.net/manual/en/function.preg-match.php</a></li> 
    <li>How to set $file to the file name, see Static and Persistent <acronym title="Uniform Resource Identifier">URI</acronym>&rsquo;s
        (<em>Coming Soon</em>) </li> 
</ul> 
<!-- <p>To view this template system in use, see the <a href="http://nedmartin.org/amused/_xml/source.php" title="Amused site code">code</a> from
    my <a href="http://nedmartin.org/amused/" title="Amused - Because someone has to be">amused
    site</a>. </p> -->
<p>&nbsp;</p> 
</body>
</html>
Last updated Tuesday, 20 November 2012
W3C CSS 2.0   
W3C XHTML 1.1