Clean PHP Templating system





1
Date Submitted Thu. Aug. 28th, 2008 9:33 AM
Revision 1 of 1
Scripter Fordiman
Tags buffering | errors | Output | PHP | template
Comments 0 comments
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.

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 '';
}
 

Comments

There are currently no comments for this snippet.

Voting

Votes Up


Scripter Fordiman
Helper mceppi

Votes Down


Coder mattrmiller