Functional HTML Rendering with PHP

When you’re working with a programming language that doesn’t have templating per default and you’re not in the mood – or don’t see the need – for templating your first course of actions is to write something to obviate having to print and concatenate everything.

In Lisp this is easier than in many other languages and looks good when used, here is an example implementation.

Now that PHP has anonymous functions something similar can be achieved there so I thought it would be fun to see what an implementation, and usage of, said implementation would look like, first the implementation:

<?php
function tag(){
  $args = func_get_args();
  $nm = array_shift($args);
  $content = array_shift($args);
  $attrs = array_chunk($args, 2);
  echo "<$nm ";
  foreach($attrs as $chunk)
    echo $chunk[0].'='.'"'.$chunk[1].'" ';
  echo '>';
  if(is_string($content) || is_numeric($content) || empty($content))
    echo $content;
  else
    $content();
  echo "</$nm>";
}

function etag(){
  $args = func_get_args();
  $nm = array_shift($args);
  $attrs = array_chunk($args, 2);
  echo "<$nm ";
  foreach($attrs as $chunk)
    echo $chunk[0].'='.'"'.$chunk[1].'" ';
  echo "/>";
}

So the first argument to our tag function is the tag name, second is the content to render inside the tag and the rest of the arguments are the attribute name and value pairs. Same goes for the etag function which renders empty elements, but then sans the content argument of course.

Below are a few examples of usage, first a simple login form.

tag('div', function(){
    tag('form', function(){
      echo 'Username:';
      etag('input', 'type', 'text', 'name', 'username');		
      echo 'Password:';
      etag('input', 'type', 'password', 'name', 'password');
      etag('input', 'type', 'submit', 'value', 'Submit', 'name', 'submit');
    }, 'method', 'post');
  }, 'class', 'normal-pad');

Then a more complicated scenario where we want to render a table of statistics:

function statsTable($stats, $headers, $fields, $sums){
  tag('table', function() use ($stats, $sums, $headers, $fields){
    tag('tr', function() use ($headers){
      foreach($headers as $header)
	tag('th', $header);				
    });
    foreach($stats as $s){
      tag('tr', function() use ($s, $fields){				
	foreach($fields as $field)
	  tag('td', $s[$field]);
      });
    }
    tag('tr', function() use ($sums, $fields){
      foreach($fields as $field)
	tag('td', is_numeric($sums[$field]) ? $sums[$field] : '');				
    }, 'class', 'sum-row');	
  }, 'class', 'stats-table');	
}

Not as pretty as the Lisp original but perhaps useful for some people who are allergic to the archetypical mixing of HTML and PHP code, the “spaghetti”.

Related Posts

Tags: ,