Original Content
  

Preview Static Free Energy

Intended Audience
Overview
Background Information
The Idea
The Code
Files and Directories
Check that the page exists

Not Wrapping Some Files
Headers and footers
Body tags and style sheets
Edit Your Apache Configuration File
About The Author


Intended Audience


This tutorial is intended for the Intermediate PHP programmer.
You will need access to your httpd.conf file, and have to feel comfortable
editing that file. You also need to be running PHP 4 and to have output
buffering turned on. (You might have to edit your php.ini file for
this).

Overview


This tutorial will show you how to produce static html pages
using PHP. This is important if you want the benefits of using PHP to build
sections of a site where the content of the pages doesn’t change very often. For
example, this system would be perfect for a magazine site which publishes its
articles to the web. With this system you can use templates to build your pages
using PHP. If you want to change the look and feel of the site, just change the
template and regenerate the pages. Since the content on those pages is not
changing, you don’t need to hit the database.


Background Information


This project came about from the FreeEnergy system of Leon
Atkinson. I love the fact that you can use templates to build pages, and PHP
functions to build parts of those templates. For example, Leon has a function to
create tables and table rows using PHP. This is much more efficient than using
the table tag in HTML. Using straight HTML, if you want to change the look of
the table, you have to do it all over the site. With FreeEnergy, you simply
change the PHP function to output a different HTML table style.

Although this was a great solution, it had two problems which
needed to be solved. One, when you want to add a page to the site, you have to
create the page and also add some information to another file. This can be a bit
tedious. Secondly, the content on the pages for a site I’m building is mostly
static, yet PHP was being used to produce every page. Under extremely heavy
loads, this is a burden, and the pages would show quicker if they were static
HTML.


The Idea


I have to admit, this idea is not my own. I went with a few
other people at work to hear a talk in Ottawa, and saw a slideshow on PHP. Part
of that tutorial was the basis of this idea.

The Code



Files and Directories


First of all, the files and directories you need. The tools
directory contains one necessary file, and other not so necessary files. The one
file that must be there is generate.php

The first part of the file just sets up some constants which
will be used later on.


<?php
    define("SERVER_NAME"$HTTP_SERVER_VARS['SERVER_NAME']);
    define("SCRIPT_NAME"basename(__FILE__));
    define("APPLICATION_ROOT"dirname(dirname(__FILE__)). "/");
    define("TOOLS"APPLICATION_ROOT "tools/");
    define("EXTERNAL_PATH",
        (dirname($SCRIPT_NAME) == '/' '/' :  dirname($SCRIPT_NAME). '/'));
    define("GENERATED_FILES"APPLICATION_ROOT.'generated/');
?>

If the directory doesn’t exist, then you need to create the
directory where the generated files will go. We don’t generate images, so we
have to copy those over. Same with the .css file.



<?php
   /* make sure the directory exists for where we will put the
      generated files. */

    if (!file_exists(GENERATED_FILES). "style.css") {
        mkdir(GENERATED_FILES0755);

        /* you might want to copy over a .css file and an images directory */
        copy(APPLICATION_ROOT'style.css'GENERATED_FILES'style.css');

        exec('cp -R 'APPLICATION_ROOT'/images/ 'GENERATED_FILES'/images/');

    }

?>

This determines the page which we will want to generate.
$SCREEN should look something like
“mydirectory/mypage.html”


<?php
    $s $REDIRECT_ERROR_NOTES;

    $d $DOCUMENT_ROOT;

    /* determine requested uri */
    $SCREEN substr($sstrpos($s$d) + strlen($d));

    $SCREEN substr_replace ($SCREEN''0strlen(EXTERNAL_PATH));
?>

Remember I said earlier that you could use PHP to generate
HTML content? Well, standard_library
has some basic functions in it. You might want to set some variables up in
global_configuration for them. For
example. You could set a variable to set the background color of your tables,
and then have a function in standard_library
which will print the table.


<?php
    /* set constants */
    if (!include_once(TOOLS 'global_configuration')) {

        echo "Unable to include 'global_configuration'<br />\n";
        exit();
    }

    /* get library of standard functions */
    if (!include_once(TOOLS 'standard_library')) {
        echo "Unable to include 'standard_library'<br />\n";

        exit();
    }
?>

Check that the page exists



This checks to make sure that the page we are trying to
generate exists. If it doesn’t, it will print out the main page, but you might
want to change it to print out a 404 page.


<?php
    /* If we aren't given a screen, go home */
    if (!file_exists(APPLICATION_ROOT$SCREEN)) {

        /* 404 page not found */
        header('Location: http://mywebserver.com/404ErrorPage.html');
        exit();
    }
?>


Not Wrapping Some Files

Of course, you won’t want to wrap every file in your website.
There are some files that probably are fine on their own.


<?php
    if (substr($SCREEN, -1) == '/') {
        $SCREEN .= "index.html";

    }

    /* If we aren't given a screen, go home */

    if (!file_exists(APPLICATION_ROOT$SCREEN)) {
        /* 404 page not found */
        header('Location: http://mywebserver.com/404ErrorPage.html');

        exit();
    }

    $PathToFile APPLICATION_ROOT.$SCREEN;
    $Wrap       TRUE;
    $PathInfo   pathinfo($PathToFile);

    if (file_exists("{$PathInfo["dirname"]}/NOWRAP")) {
        $ArrayOfFileNames file("{$PathInfo["dirname"]}/NOWRAP");

        foreach ($ArrayOfFileNames as $FileName) {
            if (trim($FileName) == trim($PathInfo["basename"])) {

                $Wrap FALSE;
                break;
            }
        }
    }

    /* only wrap files that end in .html, .htm, or .php */

    if (preg_match ('/((\.html?)|(\.php))$/') && $Wrap == TRUE) {

        $Wrap TRUE;
    } else {
        $Wrap FALSE;
    }
?>

Headers and footers

The code above puts all the content into the variables
$Buffer,
$PageTop and
$PageBottom.
$PageTop and
$PageBottom come from the files

page_top and
page_bottom in the tools directory.
(You might want to name them with a .php extension because you can put PHP
content in them.) The variable $Buffer contains the content that comes from the
page we are generating.

page_top should
contain a standard header for your page, and
page_bottom can contain a standard
footer for all your pages.


<?php

    /* Start buffering output */
    ob_start();

    if ($Wrap) {

        $ArrayOfNames = array ( 
            'Buffer'     => $SCREEN, 

            'PageTop'    => "page_top.php",             
            'PageBottom' => "page_bottom.php" 
        );

        foreach ($ArrayOfNames as $VarName => $PageName) {

            if ($VarName != 'Buffer') {
                $Directory TOOLS;
            } else {
                $Directory APPLICATION_ROOT;

            }

            if (!include_once ("{$Directory}/{$PageName}")) {
                echo "An error occured while including the screen.<br>\n";

                exit();
            }

            $$VarName ob_get_contents();
            /* $$VarName now contains the entire output. */

            /* clean it out so that the screen does not appear twice */

            /* ob_clean will be in php 4.2, for the time being we use
               the combination of ob_end_clean() and ob_start() */

            /* ob_clean(); */

            ob_end_clean();
            ob_start();
        }
?>


Body tags and style sheets

In this section, I’m adding in my own body tag, so that all
the pages have the same background color. I’m also putting in our own stylesheet
so that others don’t have to add it in.


<?php
        $Buffer eregi_replace('<body[^>]*>',
            "<body bgcolor='#D5D8E4'>{$PageTop}", 

            $Buffer);

        /* put in the style sheet */

        $Buffer eregi_replace('<head[^>]*>',
            "<head>\n<link rel='stylesheet' type='text/css' href='".EXTERNAL_PATH."style.css'>\n",

            $Buffer);

        $Buffer eregi_replace("</body[^>]*>"$PageBottom."</body>"$Buffer);

        echo $Buffer;
    } else {

        if(!include_once(APPLICATION_ROOT.$SCREEN)) {
            echo "An error occurred while including the screen.<br />\n";

            exit();
        }
    }

    /* get the output right now, which should be the complete html page we
       want to save */

    $data ob_get_contents();  
?>

This section just makes sure that all the directories exist
and then writes the content to the proper html file.


<?php
    /* go through all the directories in $SCREEN, make sure they exist. */

    $PathInfo pathinfo$SCREEN );
    $DirectoryInfo $PathInfo["dirname"];

    $ArrayOfDirs split ('/'$DirectoryInfo);

    foreach ($ArrayOfDirs as $DirectoryName) {

        $Directories .= "/".$DirectoryName;
        if (!file_exists(GENERATED_FILES$Directories))
            mkdirGENERATED_FILES.$Directories0755);

        }
    }

    $fp fopen(GENERATED_FILES."/".$SCREEN'w');
    fputs($fp$data);

    fclose($fp);

    /* Flush and turn off buffering */
    ob_end_flush();
?>


Edit Your Apache Configuration File

Finally, you need to edit your Apache configuration file and
add in a PHP script to handle 404 errors. The script should look something
like:

<Directory
"/path/to/website">

ErrorDocument 404
/path/to/website/generate.php

</Directory>

Don’t put this in a <Location> tag, it won’t
work.

Also, you need to have
output_buffering turned on. You can do
that in many ways, but I find that the easiest way is to edit the php.ini file
and set:

output_buffering =
On.

After you do both of these, you’ll need to restart your
webserver.

After all of that, you’ve got an .html page and next time
someone hits it, it won’t generate a 404 (meaning no PHP generation). Your
webserver will simply serve up the static html page.

If your layout changes, or your color scheme changes, simply
make the proper changes when you generate the PHP, and then delete all the files
in your GENERATED_FILES directory. The pages will be regenerated for you, with
the new look and feel.

If you have ideas that could improve this, please email me at
mikep@oeone.com.


About The Author

Mike Potter is an engineer with OEone Corporation.
OEone is creating an operating environment for Internet Computers. At OEone,
he’s in charge of many projects, including their websites and the calendar project.
OEone’s operating environment, Penzilla, is created in XUL, JavaScript, CSS
and XPCOM, and runs in Mozilla. The OEone calendar has been given to the Mozilla
project as the basis for their calendar project, which Mike is also in charge
of. He’s also done many websites in PHP, including the Canadian
Curling Association
and his own website, InTheHack.com.

Published: January 22nd, 2002 at 12:00
Categories: Tutorials
Tags: