Page 1 of 3

Thoughts on Templates

Posted: Sat Jun 07, 2008 6:56 pm
by mpetrovich
I have some thoughts on "templates." My personal philosophy is that templates, where possible, should never contain PHP code. Let me explain.

PHP, in its roots, has the ability to enhance an HTML page by embedding code. So quite frequently, people will create a page that looks something like this (keeping it simple):

Code: Select all

<doctype ...
<html>
<head>
<title><?php echo $mytitle; ?></title>
</head>
<body>
<div id="header">
  <?php echo $myheader; ?>
</div>
<div id="menu">
  <?php echo $mymenu; ?>
</div>
<div id="content">
  <?php echo $content; ?>
</div>
<div id="footer">
<?php echo $myfooter; ?>
</div>
</body>
</html>
The other way to generate this page, is to use a template, and insert content, using a markup. I happen to like "@@" symbols as delimiters, since they are easy to see, but others can be used as well. So, here is an non-PHP (HTML-only) template.

Code: Select all

<doctype ...
<html>
<head>
<title>@@TITLE@@</title>
</head>
<body>
<div id="header">
@@HEADER@@
</div>
<div id="menu">
@@MENU@@
</div>
<div id="content">
@@CONTENT@@
</div>
<div id="footer">
@@FOOTER@@
</div>
</body>
</html>
So, to use this template, which is pure HTML, and can be validated, you need to do something like this:

Code: Select all

<?php
$page = file_get_contents($templatefile);
 
$OldText   =  array('@@TITLE@@', '@@HEADER@@', '@@MENU@@', '@@CONTENT@@', '@@FOOTER@@');
$NewText = array($mytitle, $myheader, $mymenu, $content, $myfooter);
echo str_replace($OldText,$NewText,$page);
 
?>
Templates of elements can also be used.

Code: Select all

$MyTableRow = '<tr><th>@@THEAD@@</th><td>@@TVALUE1@@</td><td>@@TVALUE2@@</td></tr>' . "\n";
So, elements can be put in a theme file, and included in your script.

There are a number of advantages to using templates like this.
1) Your template can be validated for HTML.
2) Your template can be edited with any HTML editor. You can edit your template independent of your code.
3) It is easy to view the complete layout. It is quite difficult when the layout is spread out in several files. Typically, your template would be more extensive.
4) It is much easier to create nice-looking HTML output. It can be difficult to figure out spacing and line breaks through a bunch of print statements in several files.

I have found when looking through the templates of many of the open-source projects, it can be quite horrendous to sort through the templates that are used.

Re: Thoughts on Templates

Posted: Sat Jun 07, 2008 8:43 pm
by Eran
Others misuse of PHP and markup mixing shouldn't be cause to dismiss it. It is dependent on the programmer's experience and ability.
Your approach might be passable if the one constructing the templates has no knowledge of PHP and you feel it must be protected from it, however it has several significant shortcomings:
* You are creating an overhead with text search-and-replace routines.
* You are limiting your abilities to create more complex view logic. Some templating systems give you the ability to run simple loops, however that is not always sufficient.
* You are creating another markup language that needs to be learned to understand your templates.

For those reasons I usually use PHP directly when I pass dynamic input into my views (templates). I do try to limit the amount of PHP code in my template files, but I have no qualms about using it directly when it's needed.

Re: Thoughts on Templates

Posted: Sat Jun 07, 2008 11:20 pm
by mpetrovich
Thanks for the reply.

I should mention that I am not talking about a templating system, like Smarty or others. I am just talking about a technique. I think it is a style issue, and does help to separate the view from the code.

It is not an issue of whether you know PHP, I am assuming that the user does, although, someone designing the template may not. You do not need to learn a content mark-up, because it's your markup. Of course if you were using this on a project with multiple contributors, you will have to define standards.

I actually use this system quite a bit. I developed a framework/CMS that works similar to how I described this. After doing it this way for a couple years, I have been quite pleased, and that is what brought this up. What I have is a controller that grabs the template, the page variables (like title, etc.), and the content, and then inserts the content and variables into the template. I can select from multiple templates, and change the theme, or display a print version. For specific projects, I can also create new markup to add to the template.

In working with designers, they would provide an HTML template for the page layout, and they or I would add the markup, and the designers would not necessarily be programmers. Sometimes the templates could be quite complex, and it really helped to be able to ensure W3C compliance as well as check for HMTL problems, when having a code-free HTML template.

Good comment on search and replace overhead. I would actually have to test that. I do not know what would be faster, or what speed differences would be observed. The difference would be between reading a text file, and replacing contents and outputting the result, versus parsing a php file. I can tell you that practically, it does not matter, but you have me curious.

Now, I use php for my content, which is somewhat unusual for CMS systems, so I am completely flexible in terms of what I want to output. Again, this is not a Smarty-type system. In fact, since the template is read before the content, I can actually change the template with the content code. We are talking about static templates, with dynamic content inserted, versus dynamic templates.

But, again, I am really talking about technique. Let me provide a more simple example. I have form-generation/processing routines. I use mini-templates variables for the titles and inputs of the form elements. I can change the template variables (and CSS of course) and change how the form is displayed. My element output function searches and replaces into these mini-template variables, and outputs the result. I cannot think of a better way to do that.

So, the point of my discussion is to consider separating the templates or layout from the code, as another tool in the toolbox. Thanks for the input.

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 2:42 am
by Mordred
Separating layout from code is the problem that templates aim to solve. Different systems put the border in different places - for example Smarty says "We separate business logic from view code" - and they do it quite wrong IMO, as they just revisit the old problem of mixing HTML and code, only this time it's not HTML and PHP, but HTML and Smarty's own code. Well done, smartdonkeys.

My own template engine purposely provides only two most basic things - if you wan't to do more, write your custom view code in PHP, not another language. The two things are value substitution (what every template system does) and "conditions", which actually require very little additional syntax, while adding tremendous value (these are the two most common things one wants to do with his templates). It is also very fast, as it compiles directly into PHP code. There are other benefits as well, which are OT here, but I might share them someday, when I finally find time to make my code GPL :)

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 2:46 am
by Benjamin
++Mordred I agree completely.

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 7:45 am
by Eran
mpetrovich wrote: It is not an issue of whether you know PHP, I am assuming that the user does, although, someone designing the template may not. You do not need to learn a content mark-up, because it's your markup. Of course if you were using this on a project with multiple contributors, you will have to define standards.
I am always considering that others might need to maintain my code and try not make it difficult for them by adding another mini-language to learn. If you are developing for others, even if you do it alone keep in mind that it might someday be maintained by somebody else.
mpetrovich wrote: Good comment on search and replace overhead. I would actually have to test that. I do not know what would be faster, or what speed differences would be observed. The difference would be between reading a text file, and replacing contents and outputting the result, versus parsing a php file. I can tell you that practically, it does not matter, but you have me curious.
PHP parsing is not an overhead by itself - If there is no PHP code then there is no overhead. I'm positive that using search-and-replace is quite the overhead (that's why Smarty and its ilk use caching techniques to avoid it).

I basically agree with Mordred on what he said, and that's why I like using an MVC structure in the apps I build. I would like to see your code when you get around to open-sourcing it :wink:

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 10:06 am
by allspiritseve
mpetrovich wrote: 3) It is easy to view the complete layout. It is quite difficult when the layout is spread out in several files. Typically, your template would be more extensive.
4) It is much easier to create nice-looking HTML output. It can be difficult to figure out spacing and line breaks through a bunch of print statements in several files.
I don't see #3 as a benefit... what if you want to change the header over the span of the entire site? The whole point of splitting templates up is so static content, that stays the same across multiple pages, is kept in one file as opposed to every single template.

As far as #4, I think the standard way to do templates natively in php is like this:

Code: Select all

<h1><?php echo $title; ?></h1>
If your entire template is an html file, with php in certain sections, its much easier to keep track of "spacing and line breaks" and any other formatting you require. I am also pretty sure there won't be problems editing these files in an HTML editor, and since php is preprocessed, a validator will see blank spaces, not php code... you could also have a php block at the top that temporarily fills in the template with sample data, if you're curious what it looks like.

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 10:28 am
by mpetrovich
To answer the question on the overhead difference with embedded php versus search and replace, I did the following.

I created two identical pages with the basic structure outlined previously.

I put PHP code at the top to define all the variables ($mytitle, $myheader, $mymenu, $mycontent, $myfooter). For the content I used a couple Lorem ipsum paragraphs.

The first page uses echo statements, embedded in the document, to output the variables. The second page uses a template and does a str_replace().

I then used for each file:

Code: Select all

for ($i=0; $i<$totalcount; $i++) {
    ob_start(); 
    include $file; 
    $result = ob_get_contents(); 
    ob_end_clean();
}
I used a $totalcount of 20,000 (so I loaded 20,000 pages of each file). Here are the results (on a Windows PC system with php 5.2):
Run Time Embed = 12.7690269947
Run Time Replace = 13.4162509441
Ratio(Embed/Replace) = 0.951758210835
On a FreeBSD server, with php 4.4.8 CGI:
Run Time Embed = 3.0479700565338
Run Time Replace = 3.9502201080322
Ratio = 0.77159499298183
On a Linux server, with php 4.3.9
Run Time Embed = 2.948224067688
Run Time Replace = 3.6019420623779
Ratio = 0.81850957528774
There seems to be a difference in php versions, and server configurations. So, the difference for this page is somewhere between 5 and 20 percent. In this case I am loading a single file without any includes, so it is a simple case to compare the two approaches. With the Unix/Linix servers we are looking at 1/25,000 seconds difference per page difference.

Now, there is another way to create a simple template, and that is to use the Heredoc. Basically you create a entire php page that is one big print statement with embedded variables.

Code: Select all

print <<<PAGELBL
code . . .
PAGELBL1;
So, this really surprised me. Here are the results on my windows system:
Run Time Embed = 12.7703359127
Run Time Replace = 13.4824581146
Ratio = 0.947181575061
Run Time Heredoc = 8.36222410202
Ratio = 1.52714585939
Here are the results on a FreeBSD server, with php 4.4.8 CGI:
Run Time Embed = 3.2656750679016
Run Time Replace = 4.1001558303833
Ratio = 0.79647584213801
Run Time Heredoc = 5.5485739707947
Ratio = 0.58856114834023
On Windows, with php 5.2, the Heredoc is the fastest, but much slower on the 4.4.8 server. I would like to see what happens with other php 5.x. That is quite interesting.

Re: Thoughts on Templates

Posted: Sun Jun 08, 2008 12:05 pm
by Eran
Interesting benchmarks, thanks for the effort :)
I would suggest upgrading to PHP5 by the way, it has many improvements and is faster for most operations.

Re: Thoughts on Templates

Posted: Mon Jun 09, 2008 4:33 am
by Mordred
php/cgi < php/server module

Also your methodology for benchmarking looks wrong - I'd like to see two different php files executed through the web server with ab.exe or equivalent. Sometimes the real bottleneck is outside the measured area, or the real-use differences are lower (or higher) than measured otherwise.

Re: Thoughts on Templates

Posted: Mon Jun 09, 2008 2:21 pm
by Kieran Huggins
I think the goal of removing PHP from the view template misses the point entirely, that's not the idea behind separation. You only want display logic in your display.

Templates will always need basic language logic like looping and conditional blocks. This is definitely a job for the language, IMO.

On the other hand, a crapload of PHP in your template is a definite design smell.

Re: Thoughts on Templates

Posted: Mon Jun 09, 2008 4:40 pm
by mpetrovich
Also your methodology for benchmarking looks wrong - I'd like to see two different php files executed through the web server with ab.exe or equivalent
I did experiment with ab.exe, the apache benchmark tool, but it did not seem to work well. I then realized that it might be more appropriate to evaluate the time within the file to execute the page generation. So, using microtime set at the beginning and end, and within the include files, I was able to sum up the time involved to generate the pages. The results also had much lower variability. "Run Time" is the time to include the file, and "Page Time" is the time to generate the page, each 10,000 times.
Speed Test
Total Count = 10,000

-------PHP Version = 5.2.0-------
Run Time Embed = 6.68748784065
Page Time Embed = 0.223108291626

Run Time Replace = 7.04441785812
Page Time Replace = 0.443378686905
Ratio (Replace/Embed) = 1.98728018432

-------PHP Version = 4.3.9-------
Run Time Embed = 1.4540040493011
Page Time Embed = 0.16743636131287

Run Time Replace = 1.8359100818634
Page Time Replace = 0.39892172813416
Ratio (Replace/Embed) = 2.3825274570363

-------PHP Version = 4.4.8-------
Run Time Embed = 1.8318321704865
Page Time Embed = 0.20241498947144

Run Time Replace = 2.1751329898834
Page Time Replace = 0.48875904083252
Ratio (Replace/Embed) = 2.4146385705368

-------PHP Version = 5.2.5-------
Run Time Embed = 1.5818297863
Page Time Embed = 0.145533084869

Run Time Replace = 2.01282501221
Page Time Replace = 0.418002843857
Ratio (Replace/Embed) = 2.8722186727
So, in general, as far as execution is concerned, Replacing is twice as slow as embedding, if these are valid simulations. You do need to keep in mind that we are talking about pretty small differences. One note about str_replace(), is there is not on option to "replace once" and that does hurt the speed, because in these cases, most of the time you only want to replace once. You can do that with preg_replace(), but it runs slower. And creating a "replace_once" function is not as fast as a native function.

I have really enjoyed the comments. What I am talking about is the approach to design, which is why this is posted in this category, and some of this may be just preference and style. Everyone has definitely made me think.

I need to emphasize that I do not, nor have I ever used Smarty-style or pseudo-language templates. My discussion here was mainly about "static" templates, with dynamic content inserted, and how to best manage that.

We have talked about site templates, but we can also include other things as well. For example, I have developed e-mail newsletter systems, where templates were stored in a database. In those cases, embedding PHP is not an option. I did find that it worked better to store a complete template and insert into the template, than to create multiple fields with the header and footer, etc. So, if you ever develop such a system, you might try that and see what you think. If you want to store templates in a database, you will need a mark-up of some kind.

In regards to site templates, over the past 2-/2 years, I have developed about 2 dozen websites. I always generate a standard template and a print template. In only 3 sites, did I need to develop more, and the most I created was 5. So, I have used this technique, and actually have liked it. It is easy to create templates and review them. As I said, they are simply complete HTML documents.

The one thing I have found quite useful, is generating the page last, and I would consider that, no matter what your approach. So, I have all of the content and miscellaneous variables generated and then output the template. I have found that quite useful because you can set session variables or cookies, do header redirects, or create custom error messages from your content. In my case, content is PHP, read using ob_get_contents().

I think if you wish to embed PHP into your template, consider only using echo statements of variables. Do all the conditional stuff elsewhere, if possible. It does make it easier to manage the templates.

(OT, in regards to upgrading to PHP 5, of 24 sites, I only have had 3 where PHP 5 was available. It is still pretty sad out there. I am hoping this changes this year!)

Re: Thoughts on Templates

Posted: Mon Jun 09, 2008 5:52 pm
by alex.barylski
Kieran Huggins wrote:I think the goal of removing PHP from the view template misses the point entirely, that's not the idea behind separation. You only want display logic in your display.

Templates will always need basic language logic like looping and conditional blocks. This is definitely a job for the language, IMO.

On the other hand, a crapload of PHP in your template is a definite design smell.
I agree and disagree. :D

On one hand, templates are intended to be easy for designers with minimal/zero PHP experience. Ideally you would be able to edit a template inside a WYSIWYG only never worrying about mucknig up the HTML/PHP.

On the flipside, most designers should know enough basic PHP to handle PHP templates. if not, it should be a trivial matter to take a static HTML template and add in the loops, conditionals, etc.

Certainly the latter allows much greater flexibility, which is the approach I use.

Re: Thoughts on Templates

Posted: Tue Jun 10, 2008 1:29 am
by Mordred
Kieran Huggins wrote:I think the goal of removing PHP from the view template misses the point entirely, that's not the idea behind separation. You only want display logic in your display.

Templates will always need basic language logic like looping and conditional blocks. This is definitely a job for the language, IMO.

On the other hand, a crapload of PHP in your template is a definite design smell.
I disagree.
My approach is like this: "view" = php code + template
(i.e. to display something we init a template with some php code)
I can clearly see the point of separation - it's the "+" sign! 8) Seriously - do whatever "view logic" you want, only in the php part of the "view". The template only defines variables to be substituted. Let's start from this premise and see where it goes.

Now, at that point, this system is more useful than a mix of php and html, but still not perfect, here's a couple of typical use scenarios with their associated problems:

1. The PHP code has to deal with conditionals (if X is true, we want to display block A, if not - block B)
Hmm, but how to define A and B? In two other template files? (Argh, quickly a nightmare to support) In constants in the PHP code? (that defeats the goal we've set)

2. The PHP code has to deal with loops/arrays - you want to display an array of objects inside a template. To display a single object you need a second template O, then do a loop in PHP that gets each object, renders it with O, appends it to a string, and when all objects are done, assigns it to the original template.

3. The PHP code has to deal with greatly complex logic or layout. Is the moon risen? If so, and it's a leap year, is the user left-handed? Errm, I can't actually think of a real example, can anyone help - what is the most complex thing you have needed done with a template that didn't fit in 1 and 2? Ah, I recalled one - rendering a tree of forum posts, where replies are offset from the parent posts.

What to do with these three points - should we give the template writer the power to write code - ala Smarty - and let him deal with it? Should we let the PHP part deal with all the boring tasks? Or should we design a hybrid system :)

I don't have time to explain now how I do it, but I'm very much interested in your thoughts on the subject. A short answer is: 1. and 2. are dealt with in the template with almost no additional syntax (surely no if and loop codewords, just extending the basic "substitute this" syntax). 3 is dealt with in the PHP code. It's rare, and if it's so complex, it belongs in the PHP anyway. The result is small code on the PHP side (since all "boring" stuff is "coded" in the template, and then translated in PHP) and simple syntax on the template side (still fully wysiwyg and non-php-coder compatible)

Re: Thoughts on Templates

Posted: Tue Jun 10, 2008 1:46 am
by matthijs
The bottom line is: you have some data (maybe in a database) and it has to be inserted in your site.

Those variables need to be inserted. Those loops (show latest 10 articles) need to be performed. That "display logic" has to be run. One way or the other.

So the only question is, were do you do that? We all want to separate the layers, we agree on that. The only difference is which "style" is used. And that's a personal choice, depending on the specific situation. Do you work alone, do you work in a team, are there front-end guys not trustworthy enough to get close to php? etc etc. So a discussion like this is difficult because one person is talking apples (situation A) while the other is talking oranges (situation B).

Person A want to "completely remove php from his templates" because his situation dictates that (he doesn't trust his template guys with php maybe).
Person B just wants to separate the layers so that maintainability is maximized (he wants to be able to easily change a template without diving too deep in the back-end code).
etc

So before someone says his approach is "better", he has to carefully explain his specific situation, otherwise we keep comparing apples and oranges.