Blog app #4: the view

Published on Thursday 28 April 2016. Tagged as PHPHTML.

In a model-view-controller concept, the view is the part that renders the HTML. To make this more flexible, I have built a very simple and fast templating system.

I developed this templating system way back when I was still developing in LotusScript. This language didn't have regular expressions yet, so I came up with a solution using explode() to cut up the entire string in parts. It is both simple and super fast. The class is called 'ViewPage' and can be found in sys/classes/viewpage.php.

The constructor method

All the data needed to render the page is passed as a single enumerated array when the class is created:

function __construct( $data ){ 
	$this->data=$data; 
}

The render method

This method is imediately invoked after the class is created. The template filename is passed as argument. This function calls the process method, passing the loaded template:

function render( $file ){
	$this->process( file_get_contents( BASE.'/content/'.$file ) );
}

The template itself has simple placeholders - {{name}} - that will be filled in by the process method:

<!DOCTYPE html><html lang="en"><meta charset="utf-8">
{{meta}}
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="{{path}}/inc/favicon.ico">
<link rel="stylesheet" href="{{path}}/inc/style.css">

<header><div>
	{{topNav}}
	<i><a href="https://www.facebook.com/your-name" title="Visit me on Facebook" class="facebook" target="_blank"><svg><use xlink:href="{{path}}/inc/icons.svg#facebook-icon"/></svg></a><a href="https://github.com/your-github" title="My Github contributions" class="github" target="_blank"><svg><use xlink:href="{{path}}/inc/icons.svg#github-icon"/></svg></a></i>
</div></header>

<article>
<h1>{{title}}</h1>
{{content}}
</article>

<footer>Copyright &copy;2016 Your Name - rendered in {{renderTime}} sec.</footer>

<!-- add analytics code here -->

The process method

This is where the magick takes place: by cutting up the template in parts using the explode() function, we can extract the names of the placeholders and replace them with real content. This method makes no use of regular expressions and is both simple as lightning fast. For the content, a method name is fabricated based on the page type and then called. The code:

function process( $val ){
	extract( $this->data );
	if( isset($type) && $type=='404' ) http_response_code(404);
	$tmp=explode( '{{', $val );
	echo $tmp[0];
	for( $i=1; $i< sizeof($tmp); $i++){
		$tmp2=explode( '}}', $tmp[ $i ] );
		switch($tmp2[0]){
			case 'path': echo ROOT; break;
			case 'renderTime': echo round( microtime( true )-START_TIME , 3 ); break;
			case 'meta':
				out( '<title>'.$app['title'].($this->data['request'][0]=='index'?'':' | '.$title ).'</title>' );
				out( '<meta name="description" value="'.( isset( $content['description'] )?$content['description']:$app['desc'] ).'">' );
				break;
			case 'topNav': $this->renderTopNav(); break;
			case 'title': echo isset($title)?$title:'Error: title is missing'; break;
			case 'content':
				$fn='render'.ucfirst($type);
				if( method_exists( __CLASS__,  $fn ) ) call_user_func( array( $this, $fn ) );
				else out( '<p>Error - no page method: '.$fn.'</p>' );
				break;
			default: out( 'Error - no rule for key: '.$tmp2[0] ); 
		}
		echo $tmp2[1];
	}
}

This ends the model-view-controller part documentation. Next: while I was writing these articles, I also made search page and implemented a full text search. I'll explain how.

The Blog app project on GitHub