views:

2292

answers:

12

Hey,

Talking from a 'best practice' point of view, what do you think is the best way to insert HTML using PHP. For the moment I use one of the following methods (mostly the latter), but I'm curious to know which you think is best.

<?php
  if($a){
?>
[SOME MARKUP]
<?php
  }
  else{
?>
[SOME OTHER MARKUP]
<?php
  }
?>

Opposed to:

<?php
  unset($out);
  if($a) $out = '[SOME MARKUP]';
  else $out = '[OTHER MARKUP]';
  print $out;
?>
+7  A: 

The most important consideration is keeping the logic separate from the presentation - less coupling will make future changes to both much more straightforward.

You might even want to consider using some sort of templating system like smarty.

Similar questions:

What’s the best way to separate PHP Code and HTML?

PHP as a template language, or some other PHP templating script?

Ken
+1  A: 

Neither. Use Smarty. By separating your internal logic from the display logic you will build code that is much simpler to maintain. (Don't take the path of PHPLib's old template system that tried to completely separate PHP and HTML - it requires display logic to be intermingled with your core business logic and is very messy.) If you absolutely must generate HTML snippets in your PHP code, use your 2nd method, but pass the variable to Smarty.

Jeremy Weathers
You don't need Smarty to "separate your internal logic from the display logic". PHP is excellent at that natively.
DisgruntledGoat
A: 

It is better to completely seperate your logic (PHP code) from the presentation (HTML), by using a template engine.

It is fast and easy to insert PHP into HTML, but it gets messy very fast, and is very difficult to maintain. It is a very quick and very dirty approach...

As for which of all the template engines available in PHP is better, see these questions for example:

Treb
A: 

If a template engine seems to much of a hassle you can make your own poor man's template engine. This example should definately be improved and is not suitable for all tasks, but for smaller sites might be suitable. Just to get you an idea:

template.inc:

<html><head><title>%title%</title></head><body>
%mainbody%
Bla bla bla <a href="%linkurl%">%linkname%</a>.
</body></html>

index.php:

<?php
$title = getTitle();
$mainbody = getMainBody();
$linkurl = getLinkUrl();
$linkname = getLinkName();
$search = array("/%title%/", "/%mainbody%/", "/%linkurl%/", "/%linkname%/");
$replace = array($title, $mainbody, $linkurl, $linkname);
$template = file_get_contents("template.inc");
print preg_replace($search, $replace, $template);
?>
neu242
No, no, no! You're not using regular expressions, why use preg_replace? Use str_replace instead, it's much faster.
DisgruntledGoat
+3  A: 

For a very simple case like this, it is fine to use PHP as a template. However, if you go beyond simple logic (and you most likely will), it is a good idea to use template engines.

In Zend Framework, which uses PHP view scripts by default, the recommended way to do this would be like this:

<?php if ($a) : ?>
    [MARKUP HERE]
<?php else : ?>
    [SOME MORE MARKUP]
<?php endif ?>

The more verbose syntax makes it a lot easier to match conditional blocks in a glance than using braces.

monzee
oh seriously, what's with the "if : endif" style? the Joomla 1.5 source code uses it everywhere and it drives me insane. Brackets are simple and easy and every IDE under the sun understands then.
nickf
Joomla hasn't the nicest code in the universe but the alternate way of using conditionals can make code more readable sometimes.
Brayn
Its only good for short codeblocks. Once it gets too large, you find yourself forgetting to close blocks and then your IDE cant show you where you went wrong. { } forever! ( ruby got this VERY wrong )
Kent Fredric
+1  A: 

Smarty is ok, if you're not using a framework or when you're using a framework which doesn't have it's own templating system.

Otherwise most PHP frameworks and younger generation CMS have their own templating system.

In general the idea of a templating system is to have files which contain almost only HTML (View/Template File) and files which contain only data or business logics (Model or Controller Files).

A Template File can look something like this (example from SilverStripe):

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
        <% base_tag %>
        $MetaTags
        <link rel="stylesheet" type="text/css" href="tutorial/css/layout.css" />
    </head>
    <body>
        <div id="Main">
            <ul id="Menu1">
                <% control Menu(1) %>
                <li class="$LinkingMode">
                    <a href="$Link" title="Go to the &quot;{$Title}&quot; page">$MenuTitle</a>
                </li>
                <% end_control %>
            </ul>
            <div id="Header">
                <h1>$Title</h1>
            </div>
            <div id="ContentContainer">
                $Layout
            </div>
            <div id="Footer">
                <span>Some Text</span>
            </div>
        </div>
     </body>
</html>

You can see that there are only a few non-HTML code pieces inserted in the places where data will be inserted before the page is sent to the client.

Your code can then (simplified) rather look something like:

<?php
  unset($out);
  if($a) $out = '[SOME CONTENT TO INSERT INTO THE TEMPLATE]';
  else $out = '[SOME ALTERNATIVE CONTENT]';
  templateInsert($out);
?>

The great thing about it: Your HTML can be seen as such and changed as such, your designer can make sense of it and doesn't have to look through your code trying to get the bits and pieces together from different places without any chance to view what she's doing. You on the other hand can make changes in the logic without worries about how it will look on the page. You'll most probably also make less mistakes because your code will be compact and therfore readable.

tharkun
A: 

Do NOT use smarty - PHP is a templating system in itself. Consider using this syntax:

<?php if($a):?>
[SOME MARKUP]
<?php else: ?>
[SOME OTHER MARKUP]
<? endif; ?>
adnam
if you write spaghetti-code, are not planning to maintain that code, want to make sure you'll never scale your app or reuse your code you may want to do it like this...
tharkun
I was asking from a theoretical, 'best way to do it', point of view.
Brayn
@tharkun: Can you post smarty code equivalent to this example? I'd be interested to see how much more maintainable and scalable it is.
Bobby Jack
@Bobby Jack: I would like to ask someone else to post Smarty code because I'm not using Smarty.
tharkun
@tharkun: I guess my point was actually more generic than just smarty - can you name *any* templating engine in which the equivalent template would be simpler than the above PHP snippet? I cannot, which is why I'm on the side of "PHP is already a templating engine, let it do its job". People make ..
Bobby Jack
... out that 100% separation of layout from content is possible; after a while, all templating engines become turing-complete :)
Bobby Jack
what I'm saying is that if Bryan uses his method as the general approach, the probability that he runs into some sort of problem at one point is higher than it is for using an approach that tries to separate logics and view! it's not about simplicity, it's about maintainability, team-work, etc.
tharkun
But I think his approach /does/ separate logic and view, as much as can actually be achieved. How would you remove that logic from his example (or the equivalent smarty code) but maintain its function?
Bobby Jack
maybe we see the example from different perspectives already. for me the given example implies he has one file with both controlling structures and markup. the continuation would be to add some more controlling code and then concatenate some markup and end up with a file his designer can't read.
tharkun
if you take his example just as the template side of an already existing separation, then maybe there is nothing to remove. btw. I wasn't the one saying "use smarty by all means" I just tried to explain how the separation can work on an easy to understand level.
tharkun
+12  A: 

If you are going to do things that way, you want to seperate your logic and design, true.

But you don't need to use Smarty to do this.

Priority is about mind set. I have seen people do shocking things in smarty, and it eventually turns into people developing sites in smarty, and then some bright spark will decide they need to write a template engine in smarty ( Never underestimate the potential of a dumb idea )

If you break your code into 2 parts and force yourself to adhere to a standard, then you'll get much better performance.

PageLogic.php

<?php 

  $pageData = (object)(array());  // Handy trick I learnt. 

  /* Logic Goes here */


 $pageData->foo = SomeValue; 

 ob_start(); 
 require("layout.php"); 
 ob_end_flush();

Layout.php

 <html>
   <!-- etc -->
   <?php for ( $i = 1; $i < 10; $i++ ){ ?>
    <?php echo $pageData->foo[$i]; ?>
   <?php } ?>
   <!-- etc -->
</html>

Php Was written as a templating engine, so you at least should try use it for its designed task before assessing whether or not you need to delve into smarty.


Moreover, If you decide to use a templating engine, try get one that escapes HTML by default and you 'opt out' instead of 'opt in'. You'll save yourself a lot of XSS headaches. Smarty is weak in this respect, and because of this, there are a lot of content-naïve templates written in it.

{if $cond}
    {$dangerous_value}
{else}
    {$equally_dangerous_value}
{/if}

Is generally how Smarty templates go. The problem is $dangerous_value can be arbitrary HTML and this just leads to even more bad coding practices with untraceable spaghetti code everywhere.

Any template language you consider should cater for this concern. ie:

{$code_gets_escaped} 
{{$code_gets_escaped_as_a_uri}}
{{{$dangerous_bare_code}}}

This way your potential doorways for exploitation are easily discernible in the template, as opposed to the doorway to exploitation being the DEFAULT behaviour.

Kent Fredric
you can also do $pageData = new stdClass();, which is the same as (object)(array());
Tom Haigh
@tom, yeah, oddly, the (object) notation is somewhat faster :). Why that is however, I don't know.
Kent Fredric
1060K times/sec vs 819K times/sec odd.
Kent Fredric
That really matters for a task carried out _once_ per page request. :D (object) notation is odd and probably not known to most PHP developers.
Vadim Ferderer
the real irony is I discovered the (object) notation before the 'new stdClass' notation.
Kent Fredric
+9  A: 

-1 for the typical hysterical ‘use [my favourite templating system] instead!’ posts. Every PHP post, even if the native PHP answer is a one-liner, always degenerates into this, just as every one-liner JavaScript question ends up full of ‘use [my favourite framework] instead!’. It's embarrassing.

Seriously, we know about separating business logic and presentation concerns. You can do that — or not do that — in any templating system, whether PHP, Smarty or something completely different. No templating system magically separates your concerns without a bunch of thinking.

(In fact a templating system that is too restrictive can end up with you having to write auxiliary code that is purely presentational, cluttering up your business logic with presentational concerns. This is not a win!)

To answer the question that was asked, the first example is OK, but very difficult to read due to the bad indentation. See monzee's example for a more readable way; you can use the : notation or {}s, whichever you prefer, but the important thing for readability is to keep your HTML and PHP as a single, ‘well-formed’ indented hierarchy.

And a final plea: remember htmlspecialchars(). Every time plain text needs to go in to a web page, this must be used, or it's XSS all over the floor. I know this question isn't directly related to that, but every time we post example code including < ?php echo($title) ?> or a framework equivalent without the escaping, we're encouraging the continuation of the security disaster area that most PHP apps have become.

bobince
I quite agree that you don't need a templating engine, but the question asked about best practices, and one of the most important is the separation of business logic and presentation. You may know all about them but that doesn't mean the poster does.
Ken
I always write my answers in such a way that I assume that the poster doesn't know and more importantly that many future readers of this WIKI won't know!
tharkun
+1  A: 

also note that echo is faster then print as it doesn't return a success value.

I've also read that stepping in and out of lots of blocks of code with ?> <? is slower than echoing.

alex
A: 

Something I wish I'd known when I first started doing PHP: Keep your heavy-lifting program code as far away from your HTML output as possible. That way they both stay in large, fairly contiguous, readable chunks.

The best way I've found of doing this is to make a static HTML file first, maybe with some fake data so I can poke around and get the design right, then write PHP code to get the dynamic part of the output and glue them both together (how you do that part is up to you - you could do it with Smarty like others are suggesting).

Ant P.
A: 

If you must do it either way use the curly braces. Don't echo HTML with PHP.

Clayton