Update: After experimenting with options in array based templating engines I have discovered that it’s not practical to use PHP as the platform for this technique. The fact that PHP does not allow identical array keys means that you can’t currently implement an array based template engine with say more than one paragraph tag since the <p> is output by setting an array key as such. Anyway, read on to get the full experiment:
While reading Agile Development with Rails, I came across an idea…small but it could be fairly powerful if done right. The question came up in the book about whether to include embedded ruby (ERb) within the view document itself. I wondered how a dynamically generated HTML page could exist without this functionality in a programming language…
Coming from PHP, I naturally just assumed that web programming languages either had some way to embed dynamically executed code into view elements or would have to simply print out every single line requiring something like a heredoc:
<?php
$heredoc = <<<HEREDOC
<p> This is some HTML inside a heredoc </p>
HEREDOC;
echo $heredoc;
?>
However, PHP has great libraries for working with XML which is basically all HTML is…So let’s say we wanted to make a templating system strictly in PHP and then create a statically accessed but dynamically generated index page otherwise known as a cache…
First we’d load the page into our view.php file:
<?php
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<html>
<head>
<title>PHP: Behind the Parser</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
XML;
?>
Let’s say we want that “Hello World” to be dynamic, so we’d replace the “Hello World” with a variable:
<?php
$dynamic_variable = "Hello World";
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<html>
<head>
<title>PHP: Behind the Parser</title>
</head>
<body>
<h1>$dynamic_variable</h1>
</body>
</html>
XML;
?>
Now we have a dynamic variable in a templated system, but not all that useful. We could just write this XML to a file, name it index.html and it would be a valid cached page…but not very exciting. However, what if we use PHP’s SimpleXML module to dynamically interact with this array, now we have dynamic access to any item in the page’s HTML in object format. Let’s add a paragraph with a class of “stuff” that says “This is an added element” underneath the h1 element:
<?php
$dynamic_variable = "Hello World";
$xmlstr = <<<XML
<?xml version='1.0' standalone='yes'?>
<html>
<head>
<title>PHP: Behind the Parser</title>
</head>
<body>
<h1>$dynamic_variable</h1>
</body>
</html>
XML;
$xml = new SimpleXMLElement($xmlstr);
$paragraph = "This is an added element";
$p = $xml->body[0]->addChild('p', $paragraph);
$p->addAttribute('class', 'stuff');
?>
Pretty cool, but it still isn’t too helpful, we can access every item on the page template…but we can’t easily remove children or alter the flow of the document. What we need is something in an array format. That way, if we need to, we can push() pop() and sort any information we’d like. Additionally, we can load arrays into convenient looping methods like foreach(). So let’s build our HTML page as an array:
<?php
$page = array (
"head" => array("title" => "The Title"),
"body" => array("h1" => "Hello World!", "p" => "This is a paragraph!")
);
function assocArrayToXML($root_element_name,$ar)
{
$xml = new SimpleXMLElement("<?xml version="1.0"?><{$root_element_name}></{$root_element_name}>");
$f = create_function('$f,$c,$a','
foreach($a as $k=>$v) {
if(is_array($v)) {
$ch=$c->addChild($k);
$f($f,$ch,$v);
} else {
$c->addChild($k,$v);
}
}');
$f($f,$xml,$ar);
return $xml->asXML();
}
echo assocArrayToXML("html", $page);
?>
Nice! So now we can access any part of the page template without a bunch of messy HTML and PHP mixed together. If you look closely you don’t even have any greater than or less than symbols (other than to demarcate arrays)! Unfortunately, that’s about as far as you can go with an array. Due to the limitations of PHP, you cannot have two unique items with the same keys in an array. So in this model, I would not be able to generate more than one paragraph tag. This makes certain HTML necessities like list items impossible and thus this templating system unreasonable. The only way to make this system work would be to give each item in the array a unique id to make each key unique.