PHP Application Framework Design: 3 - Page Templates
Printable VersionLast edited on 07/02/08, 01:44 PM
This is part 3 of a multi-part series on the design of a complete application framework written in PHP. In part 1, we covered the basic class structure of the framework and laid out the scope of the project. The second part described methods for managing users and session data. This part describes a practical implementation of page templates and the separation of application logic from the presentation layer.
Templates
Wouldn't it be nice if all the pages on your site had a similar style? Yes,
it would... but that's not the only reason for using page templates. In fact,
if thats all that you require, style sheets should solve the problem with
much less overhead. If you are looking to add a simple header of footer to
every page, Apache provides that functionality via server side includes
(or you can use PHP to simply read in an file and output it to the top of
each page). In the context of this framework, however, what we are trying to
accomplish is a bit more sophisticated. In effect, templates allow us to add
a separate presentation layer to our web application. This approach is similar
(though much simpler) to the one employed in ASP.NET
There are many template engines available for PHP but the approach we will use
here is based on Brian Lozier's article Beyond The Template Engine.
The idea is that most of the existing template engines provide much more
overhead that we want for what we need to accomplish. In fact, PHP can do
what we need in just a few lines of code which open up a text file and replace
all the place-holders with dynamic content. So if we encapsulate that functionality
in a class and put a cherry on top we end up with class_template.php
and a realization of a presentation layer in our application framework.
In short, we will achieve the following benefits from implementing templates as
described below:
- Limited overhead (compared to not using templates at all)
- Separation of the business logic layer from the presentation
- Each page has a consistent feel and functionality
- Simplified site maintenance
Inside the Belly of the Beast
If you've been following this series from Part 1
you will notice that so far we have described a page as an object of a class
which performs some operations but does not output anything to the screen
(unless you decided to use your own poetic license to interprete the action
of outputting to the client's browser as just another operation). The reason
for this is that all aspects regarding the way the results is displayed are
handled by the template engine and stored in the page template files. Each
page will use the same template file (preferably) and embed the the dynamic
content using the interface provided by the template class. Actually, in the
final version of the application framework, each page reads in a generic
template for the page layout and then nests another page template as a form.
The form templates are unique to each page and allow for greater flexibility.
For now, lets just keep things simple. Read Part 4
of the series to see how the forms are implemented.
Page templates, as implemented in this framework, are nothing more that PHP files.
In fact, you can place any valid PHP command into these files but we will employ
the honor principle to ensure that you don't. After all, the goal was to separate
the presentation layer from the application logic and placing code into these
template files defeats that purpose. To embed the dynamic content into the
templates simply place a PHP variable into the template file like so:
<?=$Title?>.
Then, inside the class for this page, we
can set the variable as follows: $this->page->set("Title","Page Title");.
Everything else is taken care of by the framework. All you have to do is
specify the right template file to use and do write the line
echo $this->page->fetch($this->template);
when you are ready
to output the result to the screen. (And even that part is taken care of for you in
the base class)
If using the template engine doesn't seem too difficult, look how easy
it is to implement the engine itself. Since we are using PHP files as
templates, the PHP parser will take care of all the hard work. All we
need to do is maintain an array of values that we want to assign to
the place-holders (i.e. when you use the set() method).
Then we need to implement a fetch() method which will extract
the values used for the place-holders into the local namespace, read
the template file into an output buffer, and then return the results.
Here is the code in all its glory:
function fetch($file) {
extract($this->vars); // Extract the vars to local namespace
ob_start(); // Start output buffering
include($this->path . $file); // Include the file
$contents = ob_get_contents(); // Get the contents of the buffer
ob_end_clean(); // End buffering and discard
return $contents; // Return the contents
}
This approach has several advantages compared to other template engines
which implement their own parser to parse the page templates. First of
all, we have all the power and speed of PHP at our disposal. If occasionally
we have to sneak a little logic into the template files then we have the
option to do so. Furthermore, the templates execute as fast as PHP itself
so we are not adding much overhead to the generation of each page. Template
engines that have their own parsers implemented in PHP are slower and those
that are implemented in C require installing extra modules on the web server.
Finally, the users of the template engine (i.e. the page designers) do not
need to learn a new syntax to create the files (and if they know PHP then
even better). All in all, this gives us a pretty good design, if I do say
so myself. Summary
At this point we have a fairly usable framework. However, we have not addressed several key goals: managing data in each page every time the page is submitted and displaying the data uniquely for each page using page templates. Both of these issues are resolved in Part 4 of this series using Forms.
Navigate: Part 1: Getting Started, Part 2: Managing Users, Part 3: Page Templates, Part 4: Forms and Events
