Categories


Loading feed
Loading feed

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.

Comments