There are lots of different methods of implementing design templating in PHP and I pretty much hate them all. So I came up with a new one, which may not be better than the others but at least it’s different.
The template markup is stored all in one file, creatively titled template.php. For organization I stuck it in my /includes folder.
Each content page is in a directory called /pages. So my login page is in /pages/login.php. The content pages don’t contain any calls to the template at all, they contain only the logic/output for that particular page.
The template page is called with a filename in the URL, i.e. template.php?page=login. This little peice of code hangs out near the top of the template page, before any HTML output (but after all the includes for various libraries / any session or cookie handling):
$page = $_GET['page'];
//output buffering is needed so we don't puke the contents of the page above the HTML headers
ob_start();
//Check to see if the file exists
if(file_exists($_SERVER['DOCUMENT_ROOT'].'pages/'.$page.'.php')){
//if so, require it
require $_SERVER['DOCUMENT_ROOT'].'pages/'.$page.'.php';
} else {
//if not, returna 404 error
header("HTTP/1.0 404 Not Found");
exit;
}
//store the output of our page in a variable
$content = ob_get_contents();
//empty the output buffer
ob_end_clean();
You need to include the page in the template before the start of the HTML output or else any cookie/session stuff in the page won’t work. Buffering the output lets you call the script now but not display its contents until later.
In the middle of our template markup, where we want the page content to appear, there’s a simple <code>echo $content</code> to place the output on the page.
Of course at this point if you want your template to show up you have to access everything through template.php. http://www.whatever.com/includes/template.php?page=login is not an attractive address. So I use mod_rewrite to hide it.
Putting these lines in my .htaccess file lets us use nice urls like “http://www.whatever.com/login.php”
RewriteEngine on
RewriteRule ^(.*)\.php include/template.php\?p=$1 [QSA]
RewriteRule ^$ include/template.php\?p=index
The first line just turns on the rewrite engine. The second sends anything ending in PHP to the template page. The QSA flag passes the query string along with it, so mypage.php?id=foo will still pass ‘foo’ correctly.
The last line handles the index page redirect for us if they just come to the bare domain and not a particular page.
Additionally it’s a good idea to add a couple lines to not redirect files which are already in our root directory.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
If you are of the opinion that this is a terrible idea which should never be used, I’d love to hear why. I really doubt I’m the first person to think of it, but I’ve never seen anyone else do it, so I’m wondering if there’s something terrible about it that I’m not aware of. I know there’ll be a performance hit with mod_rewrite, but pretty much every other CMS I’ve seen uses mod_rewrite to make their URLs pretty, so I’m not convinced it’s any worse than the other stuff that’s out there.