Preview Static Free Energy
by Mike Potter
|
0 comments | Tuesday, January 22, 2002
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_FILES, 0755);
/* 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($s, strpos($s, $d) + strlen($d));
$SCREEN = substr_replace ($SCREEN, '', 0, strlen(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))
mkdir( GENERATED_FILES.$Directories, 0755);
}
}
$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.

Comments