PHP Template Engine Intro

[email protected] (Andrei Zmievski)
Newsgroups php.template
Message-ID <[email protected]>
PHP Template Engine
-------------------

It is undoubtedly one of the mosted asked questions on the PHP mailing
lists: how do I make my PHP scripts independent of the layout? While PHP is
billed as "HTML embedded scripting language", after writing a couple of
projects that mixed PHP and HTML freely one comes up with the idea that
separation of form and content is a Good Thing [TM]. In addition, in some
companies the roles of layout designer and programmer are Consequently, the
search for a templating solution ensues.

Most of the time these souls are pointed to the FastTemplate. It provides a
way to substitute variables into the template and do a limited form of
dynamic block functionality. Unsatisfied with this, I wrote a class called
SmartTemplate which, aside from regular variable substitution, supported
including other templates, integration with config files, embedding PHP
code, limited 'if' statement functionality and much more robust dynamic
blocks which could be multiply nested. It did all this with regular
expressions and the code turned out to be rather, shall we say,
impenetrable. Ever since I've wanted to build a template engine directly
into PHP.

The desire for this is twofold. Firstly, having it in PHP itself means that
we can make it very fast without relying on regular expressions. Secondly,
it would provide immediate support for include statement, embedded PHP code
evaluation, possible support for compiled and cached templates in the
future, and other benefits.

In our company, for example, the development of an application goes on as
follows. After the requirements docs are done, the interface designer makes
mockups of the interface and gives them to the programmer. The programmer
implements business logic in PHP and uses interface mockups to create
skeleton templates. The project is then handed off to the HTML designer/web
page layout person who brings the templates up to their full glory. The
project may go back and forth between programming/HTML a couple of times.
Thus, it's important to have good template support because programmers don't
want anything to do with HTML and don't want HTML designers mucking around
with PHP code, and designers need support for config files, dynamic blocks
and other stuff, but they don't want to touch the PHP code.

With all this in mind, I am at a point where I can start the development of
the PHP templating solution, but I need your help. I have a fairly good idea
of how it will function and what the template syntax would be, but perhaps
there are better ideas floating out there that have never been discussed in
public. I've created a mailing list that you can subscribe to by sending
e-mail to [email protected]. Please read the following
short design document and let's start talking about how to make PHP
templates rock.

---------------------------------------------

Template Language
-----------------

The templates would consist of straight HTML interspersed with template
language commands. The commands are enclosed between { and } characters.

{<variable>}
	- prints out the value of the variable

{%<variable>}
	- prints out the value of the configuration variable

{# ... #}
	- comment, does not show up in PHP, does not show up in HTML

{%xx}
	- prints out ASCII character specified by xx (mostly to support putting
	  { and } in the HTML directly.

{config: <file> [: <section>]}
	- loads globals settins from config file, optionally loading values
	  from specified section

{dynamic: <name>}
	...
{/dynamic}
	- defines a dynamic block that can be optionally parsed or looped


PHP Template interface
----------------------

resource tpl_load(string tpl_name [, path_to_templates [, string path_to_configs]])
	- loads a template and performs initial parsing which includes replacing
	  the config variables with their values, stripping comments, and
	  printing out {%..} constructs.

void tpl_assign(resource tpl, string varname, mixed value)
	- assigns the value to the specified template variable

void tpl_assign(resource tpl, array vars)
	- assigns key/values of array as template variable names and values

void tpl_parse_dynamic(resource tpl, string block [, bool append])
	- parses a dynamic block optionally appending the result to the previous
	  parsed result

void tpl_clear_dynamic(resource tpl, string block)
	- clears the previously parsed contents of the dynamic block

void tpl_parse(resource tpl)
	- parse the template, substituting the variables

string tpl_fetch(resource tpl)
	- returns the parsed contents of the template which should be straight
	  HTML

Some other possible ones that come to mind:

tpl_unset_var(resource tpl, string varname)
	- unset template variable

tpl_unset_conf_var(resource tpl, string confvarname)
	- unset template config variable


If there are nested dynamic blocks, then the parsing should proceed from the
innermost block to the outermost. If the parent block is parsed before the
child one, then the contents of the child block within the parent one would
be empty.

If the top template file loads config var TITLE, for example, and the
included template loads TITLE from another section of config file, then it
will be valid only in the scope of the included template. Basically, the
config vars in the included templates override the config vars inherited
from the parent template, but only within their scope.

Another sticky issue is whether the parsed contents of the child block
should be automatically cleared once the parent block is parsed.

Maybe path_to_templats, path_to_configs should be .ini settings.

Sometimes there are also situations where you want to show either one or the
other dynamic block, for example, when doing search they may or may not be
search results. With the proposed interface you'd have to define two dynamic
blocks on the same level and then parse either one or the other. The
unparsed one simply wouldn't show.

I will probably also write an extension for dealing with config files in
PHP. Something like config_load() which can be used to load global config
vars or a section.

I know this interface mostly resembles FastTemplates, but that's why I'd
like to have a good discussion on how templates should work in PHP. Maybe
there's a better way to do dynamic blocks. Maybe config file integration can
be different. Let's brainstorm, but keep in mind that HTML designers will
need to use this as well, not just the programmers. With this in mind, I'm
going to invite one of our HTML designers to be on the list and if you want
to bring more, go ahead.

Cheers,

-Andrei
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.