Well, that's why a CMS is used for a lot of sites -- generally what I've been doing lately on sites that are pretty much static content is instead of using a database driven CMS, I use what's called a "poor man's system" -- mine is actually pretty complex as it uses the 'one index to rule them all' using a htaccess whitelist and a real templating system...
But you could easily do a dirt simple one using PHP by simply having:
template.php
<?php
function template_header(
$pageTitle = false,
$keywords = false,
$description = false
) {
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
lang="en"
xml:lang="en"
<head>
<meta
http-equiv="Content-Type"
content="text/html; charset=utf-8"
/>
<meta
http-equiv="Content-Language"
content="en"
/>
<meta
name="viewport"
content="width=device-width; initial-scale=1.0"
/>';
if ($keywords) echo '
<meta
name="keywords"
content="', $keywords, '"
/>';
if ($description) echo '
<meta
name="description"
content="', $description, '"
/>';
echo '
<link
type="text/css"
rel="stylesheet"
href="screen.css"
media="screen,projection,tv"
/>
<title>
', ($pageTitle ? $pageTitle . ' - ' : ''), ' Site Title
</title>
</head><body>
<div id="top" class="widthWrapper">
<h1>
Site Title
<span><!-- image replacement --></span>
</h1>
<ul id="mainMenu">
<li><a href="#">Home</a></li>
<li><a href="#">Forums</a></li>
<li><a href="#">FAQ</a></li>
<li><a href="#">ContactUs</a></li>
</ul>
<hr /><!-- remove if content starts with numbered heading -->
<div id="contentWrapper"><div id="content">';
// using double-wrapper for fluid content-first columns
} // template_header
function template_footer($extrasFile = false) {
echo '
<!-- #content, #contentWrapper --></div></div>
<div id="extras">';
// any static / common to all pages sidebar stuff here
if ($extrasFile) include($extrasFile . '.php');
echo '
<!-- #extras --></div>
<div id="footer">
Disclaimer / Other footer stuff here
<!-- #footer --></div>
<!-- #top.widthWrapper --></div>
} // template_footer
?>
Which contains all the code that is common to every page. You then for example would have a 'index.php' like this:
index.php:
<?php require_once('template.php'); template_header(
false, // don't show "pageTitle - Site title"
'seven,or,eight,words,that,exist,in,body', // keywords
'A short natural language description describing the site'
); ?>
<h2>Content goes here</h2>
<p>
This is where your page unique content would go!
</p>
<?php template_footer('normalExtras'); ?>
The 'normalExtras.php' file would simply be the content you have in your sidebars. I do it as separate files so that sub-pages can have their own unique sidebar content instead of the same as every page.
If for example, you had your FAQ:
faq.php
<?php require_once('template.php'); template_header(
'Frequently Asked Questions',
'frequently, questions, one, two, three', // keywords
'Frequently asked questions about "describe the site's purpose here"'
); ?>
<h2>Frequently Asked Questions</h2>
<h3>Question one?</h3>
<p>
Answer to question one.
</p>
<h3>Question two?</h3>
<p>
Answer to question two.
</p>
<h3>Question three?</h3>
<p>
Answer to question three.
</p>
<?php template_footer('normalExtras.php'); ?>
That's in essence a very basic poor mans -- and can easily be done in PHP, ASP, PERL -- even SHTML (an Apache only built-in SSI system)
As to keeping the HTML extension, I'd set up a 301 "moved permanently" redirect handler to point at the new versions of the pages. A "one index to rule them all" system might be better suited to handling that -- particularly since you could then use a rewriterule to use "friendly" uri's... so instead of "/faq.html" it would just be "/faq". No extension needed. You could even keep the HTML extension if you parsed $_SERVER['request_uri'] server-side instead of trying to use some fancy htaccess parsing.
For example, in .htaccess I usually use this:
RewriteEngine On
RewriteRule !\.(gif|jpg|png|css|js|txt|ico|zip|gz|rar|pdf|xml|wav|mp3|mp4|mpg|flv|swf|mkv|ogg|avi|webm|woff|svg|eot|ttf)$ index.php
It's a whitelist -- any file extension not on that list is routed to my index.php -- I use that one single index.php to parse $_SERVER thus:
<?php
// define('TESTING', 1);
define('CONTENT_ENCODING',
(strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip') !== false) ? 'x-gzip' :
(strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) ? 'gzip' :
false
);
define('CONTENT_ENCODING', false);
if (CONTENT_ENCODING) {
ob_start();
ob_implicit_flush(0);
register_shutdown_function(function() {
header('Content-Encoding: ' . CONTENT_ENCODING);
$contents = ob_get_contents();
ob_end_clean();
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00",
substr(gzcompress($contents, 6), 0, -4);
});
}
function cleanPath($path) {
return trim(str_replace(['\\','%5C'],'/',$path),'/');
}
function bomb($title, $message) {
template_header('ERROR - ' . $title);
echo '
<div id="fatalError">
<h2>
',$title,'
</h2>
<p>',$message,'</p>
<p><strong>EXECUTION HALTED</strong></p>
<!-- #fatalError --></div>';
template_footer();
die;
}
final class request {
private static $data = [];
public static function value($index = 0, $clean = false) {
if ($index === true) { $index = 0; $clean = true; }
if (count(self::$data) == 0) {
$path = cleanPath(parse_url($_SERVER['REQUEST_URI'],PHP_URL_PATH));
if (strpos($path,'..')) bomb('hackingDetected', 'uptreeFail');
$path = substr($path, strlen(HTTP_ROOT) - 1);
self::$data = empty($path) ? ['default'] : explode('/',$path);
foreach (self::$data as &$p) $p = urldecode($p);
}
return isset(self::$data[$index]) ? (
$clean ? cleanName(self::$data[$index]) : self::$data[$index]
) : false;
}
} // class request
define('SCRIPT_FILENAME',cleanPath($_SERVER['SCRIPT_FILENAME']));
define('HTTP_ROOT',str_ireplace('index.php','',$_SERVER['PHP_SELF']));
define('LOCAL_ROOT',str_ireplace('index.php','',SCRIPT_FILENAME));
define('HTTP_THEME', HTTP_ROOT . 'theme/');
require_once('theme/index.template.php');
require_once(
is_file($targetFile = 'statics/' . request::value() . '.php') ?
$targetFile :
'statics/404.php'
);
?>
That's actually lifted right straight from one of my sites. "cleanPath" strips out all slashes preventing loads from anywhere but /statics...
/theme/index.template.php is pretty much identical to the above template.php
/statics/default.php would be the default/home page, what would normally be a index.php or index.html
The cute part is, that with the above system in place, you could make:
/statics/faq.html.php
... and your url to that file would actually work as http://www.yoursite.uri/faq.html
Kind of what you are looking for?