Lots of people swear by Smarty or any one of a number of template engines out there. However, I’m a bit stubborn, and like to reinvent the wheel. After all, PHP really is a template engine in and of itself. So I’ve been fighting with writing a template wrapper, and I had a pretty decent system worked out where I’d include an html file with comment tags that get replaced with PHP Values. For instance:
<html>
<body>
<!–CONTENT–>
</body>
</html>
So, I decide that that’s not enough, and I want to be able to include php in my templates and have it executed. Now, I couldn’t think of a simple way to handle it, so I added a regular expression to get any code enclosed in php tags () within the html.
$expression = '/<\\?php(\\s+)(.*?)(\\s)\\?>/s';
// The trailing “s” there lets the “.” metachar accept newlines.
$file_data = preg_replace_callback($expression, ‘preg_execute_php’, $file_data);
function preg_execute_php($matches) {
$php_code = trim($matches[2]);
ob_start();
eval($php_code);
$php_output = ob_get_contents();
ob_end_clean();
return $php_output;
}
You still with me? Yeah, it’s a mess. But it works good. preg_replace_callback just calls the callback function on each match made by the expression, and then replaces the full match with what the function returns. So, now we can use a standard php-embeded html file.
Even better, the scope of the eval’d file is within a function, so we don’t have to worry (much) about namespace collisions. However, this only allows you to do blocks of self-contained code; you can’t do inline loops (where you escape in and out of php) or anything fun. So I set to work to make it even better.
The problem is that eval() expects php code. So we can fake it out by telling it that the code it’s getting is php, even if it’s not. We do this by adding a php closing tag at the beginning of the text string.
ob_start();
eval(’?>’.$file_data);
$file_data = ob_get_contents();
ob_end_clean();
Still with me? So whatever file we pass in is now being executed, and the contents buffered. So you can have templates with pure inline php. Now, we wrap this in a class (so that we can set local variables in the template files), and call it a day.
Here’s the finished product. And here’s an example template.
[Edit: gotcha! xml declarations within your code (necessary for xhtml validation) will try to be executed by eval(). We need to remove those before execution. The template code above has been updated with this.]