Clean PHP Templating system
1
Fordiman
Best use of ob_, custom error handling, and variable variales evar: simple templating.
_parse($filename[,$locals])
includes $filename and renders its output to the return value. $locals, if used, will add a set of variables to the included context.
Parse($template[,$locals])
Same as above, but allows you to define a base template folder and omit the .php - just for cleaner code.
t($template[,$obj])
...
t()
Same as Parse, but any output between the opening call and the closing call (no arguments) will be buffered intot he $content variable of the template.
Play around with t(..) to find out more; I don't feel like documenting it.
_parse($filename[,$locals])
includes $filename and renders its output to the return value. $locals, if used, will add a set of variables to the included context.
Parse($template[,$locals])
Same as above, but allows you to define a base template folder and omit the .php - just for cleaner code.
t($template[,$obj])
...
t()
Same as Parse, but any output between the opening call and the closing call (no arguments) will be buffered intot he $content variable of the template.
Play around with t(..) to find out more; I don't feel like documenting it.
define('DEBUG',false);
function ErrorCache($errno, $errstr=null, $errfile=null,
$errline=null, $errcontext=null) {
//constant stack
static $_ERRORS=Array();
//set the error handler and push new array to stack
if ($errno===EC_START) {
set_error_handler('ErrorCache',E_ALL);
$_ERRORS[]=Array();
return true;
}
//Clean the error handler, and pop top of stack
if ($errno===EC_END) {
restore_error_handler();
return array_pop($_ERRORS);
}
//Reference top of stack
$lastErrors=&$_ERRORS[count($_ERRORS)-1];
//String representations of PHP Error types
$errorTypes = Array(
E_ERROR => 'Fatal Error',
E_WARNING => 'Warning',
E_PARSE => 'Parse Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Fatal Core Error',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_ERROR => 'Compilation Error',
E_COMPILE_WARNING => 'Compilation Warning',
E_USER_ERROR => 'Triggered Error',
E_USER_WARNING => 'Triggered Warning',
E_USER_NOTICE => 'Triggered Notice'
);
//Obey error reporting rules
//if ((error_reporting() && $errno)==0) return true;
//Just cache the error as an Object
$ret=(object)Array(
'number'=>$errno,
'message'=>$errstr,
'file'=>$errfile,
'line'=>$errline,
'context'=>$errcontext,
'type'=>$errorTypes[$errno]
);
$lastErrors[]=$ret;
$n=$ret->number;
if ($n==E_ERROR || $n==E_PARSE ||
$n==E_CORE_ERROR || $n==E_COMPILE_ERROR || $n==E_USER_ERROR) {
while (ob_end_flush());
echo $x=formatErrors($lastErrors);
fwrite(fopen('error.log','w'),$x);
}
return true;
}
function formatErrors($errors) {
if (!DEBUG) return '';
$ret='';
if (count($errors)>0) {
$ret.='<ul class="error"'.(DEBUG?'':' style="display: none"').'>';
foreach ($errors as $error)
$ret.=
'<li>'.
'<b>'.$error->type.'</b>: '.
$error->message.
'<blockquote>'.
'<i>file</i>: '.$error->file.'<br />'.
'<i>line</i>: '.$error->line.
'</blockquote>'.
'</li>';
$ret.='</ul>';
}
return $ret;
}
function _parse($_FILE, $_LOCALS=false) {
global $argv;
if ($_LOCALS===false) $_LOCALS=Array();
$_LOCALS=(array)$_LOCALS;
//Output buffering here prevents bad variable naming in the
//LOCALS object from spitting out notices
ob_start();
foreach ($_LOCALS as
//Long var names to avoid collisisions with template vars
$toDodgeCollisionsName=>$toDodgeCollisionsVar) {
$toDodgeCollisionsName=trim($toDodgeCollisionsName);
$$toDodgeCollisionsName=$toDodgeCollisionsVar;
}
ob_end_clean();
unset($toDodgeCollisionsName,$toDodgeCollisionsVar);
//Start buffering
ob_start();
// Start error caching
ErrorCache(EC_START);
//Grab the file
if (file_exists($_FILE)) include($_FILE);
//grab the errors it returned
$errors=ErrorCache(EC_END);
//grab the stdout it returned
$ret=ob_get_contents();
//clean the buffer and stop
ob_end_clean();
//return the buffer plus formatted errors
return $ret.formatErrors($errors);
}
define('TPLDIR',rtrim($_SERVER['DOCUMENT_ROOT'],'/').'/tpl/');
function Parse($_TEMPLATE, $_LOCALS=false) {
$tpl=findPath(TPLDIR.$_TEMPLATE.'.php');
$_LOCALS=(object)$_LOCALS;
$_LOCALS->_TEMPLATE=$_TEMPLATE;
return _parse($tpl, $_LOCALS);
}
define('TPL_BLOCK',false);
define('TPL_END',NULL);
define('TPL_CONTENT','$content');
function t($tpl=null,$newObj=null) {
static $tplStack=Array();
if ($newObj===null) $newObj=Array();
$newObj=(array)$newObj;
if ($tpl===TPL_BLOCK) {
//called with TPL_BLOCK
list($tpl, $obj, $lst)=array_pop($tplStack);
$obj=array_merge($obj,(array)$newObj);
$ct=trim(ob_get_contents());
if (!isset($obj[$lst])) $obj[$lst]=$ct;
else if (!is_array($obj[$lst]))
$obj[$lst]=Array($obj[$lst],$ct);
else
$obj[$lst][]=$ct;
$tplStack[]=Array($tpl, $obj, $lst);
ob_end_clean();
ob_start();
return '';
}
if ($tpl===TPL_END) {
//called without arguments
t(TPL_BLOCK); //Finish off this block
ob_end_clean(); //stop buffering
list($tpl, $obj, $lst)=array_pop($tplStack);
$obj=array_merge($obj,(array)$newObj);
if (is_array($obj['content'])) {
$obj['_blocks']=$obj['content'];
$obj['content']=join('',$obj['_blocks']);
}
$errors=formatErrors(ErrorCache(EC_END));
return Parse($tpl,$obj);
}
if (substr($tpl,0,1)=='$') {
$var=substr($tpl,1);
t(TPL_BLOCK); //finish off this block
list($tpl,$obj,$last)=array_pop($tplStack);
$obj=array_merge($obj,(array)$newObj);
$tplStack[]=Array($tpl,$obj,$var);
return '';
}
$tplStack[]=Array($tpl, (array)$newObj, 'content');
ErrorCache(EC_START);
ob_start();
return '';
}






There are currently no comments for this snippet.