Template Driven PHP Architecture
by Marc Plotz
September 15, 2009
|
Discover the power of PHP Templating with Marc Plotz.
|
Introduction
Much thought went into writing the first line of this
article. I thought about a lot of things to say that would
probably sound smart or at least vaguely intelligent--then I
thought better if it. You are here to learn about
templating, aren't you? Let's get right to it then.
What I am confronted with every day is the clash between
designers and developers. This is more of a metaphorical one
than a real thing, but it exists. The problem is that
the two worlds cannot meet on solid ground. The designer
thinks in terms of style, shapes, layouts, while the
developer thinks in terms of code, structure and
architecture. But there is some point--albeit shaky--where
the two meet, and that is called HTML.
The designer has a final result that is HTML. At the end
of the day his work becomes an HTML layout complemented by
CSS. The developer starts with the HTML that the designer
has created and then makes his code render it dynamically.
So it is here, at this meeting point that is HTML that we
must find a way for designer and developer to meet and do
what they both need to do without stepping on each other's
toes.
Assume for a minute that a designer has designed a simple
HTML Table that will display the details of members on a
website in a simple list display. What if we could let the
designer simply tell us where he wanted the developer to
insert the dynamic content and simply leave it to him? What
if, rather than having to explain complex concepts, the
designer could simply say:
<table>
<tr>
<td><b>Username</b></td>
<td><b>Email</b></td>
<td><b>Password</b></td>
</tr>
<!--START-->
<tr>
<td> <!--USERNAME-DATA--> </td>
<td> <!--EMAIL-DATA--> </td>
<td> <!--PASSWORD-DATA--> </td>
</tr>
<!--END-->
</table>
So now the developer knows exactly what data needs to go
where. All he has to do is write a script to handle this
type of thing. This might take the form of:
<?php
$template_name = "userlist.html";
// get database data
$rules = array (
array ("<!--USERNAME-DATA-->", "0"),
array ("<!--EMAIL-DATA-->", "1")
array ("<!--PASSWORD-DATA-->", "2")
);
$contents = get_template($template_name, $rules, $recordset_array);
while (list ($line_num, $line) = each ($contents))
{
echo "$line";
}
?>
What we now have is a PHP script that will substitute
definite values for the comments that the designer inserted
into the HTML in the first place. Thus we now need to finish
the parser that will make sure that the code we have just
written will actually do what the designers intended.
function get_template($template_name, $rules, $recordset_array)
{
$FLAG = 0;
$start=0;
$end=0;
$res_arr="";
$xcontents = file (TEMPLATES_PATH . $template_filename);
while (list ($line_num, $line) = each ($xcontents))
{
if ($FLAG == 0)
{
if(ereg('<!--START_ROW-->', $line))
{
$FLAG = 1;
$start = $line_num;
}
}
else
{
if (!ereg ('<!--END_ROW-->', $line))
{
$res_arr .= $line;
}
else
{
$FLAG = 0;
$end = $line_num;
}
}
}
$tmp_res_arr = "";
$n = count($data_array);
for ($x=0; $x<$n; $x++)
{
$tmp = $res_arr;
for ($y=0; $y < count($rules); $y++)
{
$a = $rules[$y][0];
$b = $rules[$y][1];
if (ereg ("<!", $a))
{
$data_array[$x][$b] = stripslashes ($data_array[$x][$b]);
eval ("\$tmp = str_replace (\"$a\", \$data_array[\$x][$b], \$tmp);");
$tmp = stripslashes($tmp);
}
}
$tmp_res_arr .= $tmp;
}
$res_arr = $tmp_res_arr;
$n = count($xcontents);
for ($x=0; $x<$n; $x++)
{
$y = $start + ($x - $end) ;
if (($x >= $start) and ($x < $end))
{
if ($contents[$start] == "")
$contents[$x] = $res_arr;
}
elseif ($x > $end)
$contents[$y] = $xcontents[$x];
else
$contents[$x] = $xcontents[$x];
}
return ($contents);
}
Ok, so lets take a look at this in a bit of detail.
$xcontents = file (TEMPLATES_PATH . $template_filename);
while (list ($line_num, $line) = each ($xcontents))
{
if ($FLAG == 0)
{
if(ereg('<!--START-->', $line))
{
$FLAG = 1;
$start = $line_num;
}
}
else
{
if (!ereg ('<!--END-->', $line))
{
$res_arr .= $line;
}
else
{
$FLAG = 0;
$end = $line_num;
}
}
}
What we are doing here is looking for the spot that the
designers said we need to include our files. Once we find
where we start, we look where we need to end. How do we
actually look for the start and end points, you may ask?
Ever heard of the built in PHP function
ereg()? What this does it search through
our code until it finds something that matches our start and
end tags. When it finds the match it RETURNS
TRUE. Note that this function has been removed from
PHP 6, but for our purposes it still works quite well. If
you really are a stickler and want to use the PHP6
functions, you need to look at PREG_MATCH().
You can see some of this HERE.
for ($x=0; $x<$n; $x++)
{
$tmp = $res_arr;
for ($y=0; $y < count($rules); $y++)
{
$a = $rules[$y][0];
$b = $rules[$y][1];
if (ereg ("<!", $a))
{
$data_array[$x][$b] = stripslashes ($data_array[$x][$b]);
eval ("\$tmp = str_replace (\"$a\", \$data_array[\$x][$b], \$tmp);");
$tmp = stripslashes($tmp);
}
}
$tmp_res_arr .= $tmp;
}
Here we loop through the data array looking for the
specific tags (USERNAME-DATA, etc), again using
ereg(); Then here and in the next code we
replace those tags with the content.
for ($x=0; $x<$n; $x++)
{
$y = $start + ($x - $end) ;
if (($x >= $start) and ($x < $end))
{
if ($contents[$start] == "")
$contents[$x] = $res_arr;
}
elseif ($x > $end)
$contents[$y] = $xcontents[$x];
else
$contents[$x] = $xcontents[$x];
}
On the whole the process is simple. What happens here is
that PHP is actually taking the HTML and replacing the
comment tags between the START and END comments with
variables drawn from the database. This might be a little
more complex than the MVC template files of the format
.phtml, but the complexity might actually be worth it in the
long run if you are not really willing to go the MVC route
and have a MODEL, VIEW and CONTROLLER for the website or
application you are building.
Until Next Time - Happy Templating!
About the Author
Marc Steven Plotz is a Senior Software
Developer for a major South African web development company
specializing in the development of enterprise-class web
applications and rapid application development frameworks.
He is also a technical writer for various developer websites
focusing on open source topics like PHP, CSS, HTML and
Javascript. He lives in Pretoria, South Africa, with his
wife and two children.
|