I really don't like mixing PHP and HTML. Mixing them makes it difficult to maintain both the PHP and the HTML, and it just makes sense to keep the two apart.
See also the question [1] on whether PHP is a good enough templating system on its own.
What's the best way to do it?
To separate your PHP and HTML as much as possible you need a small template class and a small set of rules to follow.
date()
.foreach
, no for
or while
loops.if
statements should only check a variable for true. All boolean logic should be pre-computed.else
is OK.If you need to alternate a color, either pass boolean values with your array for each row or use ($i++%2)
. Then in your view you will use an inline if
:
<div class='menu <?=($link['alternate'])?'white':'grey'?>'>
If you need to check for the beginning or end of a list, pass a flag in the associate array that you're currently iterating through.
To make simple or advanced web site you need something that can hold data and a file path. With the below classes you create a new Template object and bind some data to it as it is created.
$main = new Template('mainView.php', array('title' => 'example page'));
Now in your view file mainView.php you access the title like this.
<?= $title; ?> // php 4 version
<?= $this->title; ?> // php 5 version
The reason you use an object instead of just an include file is to encapsulate data. For example:
$main = new Template('mainView.php', array(
'title' => 'example page',
'leftMenu' => new Template('linkView.php', array('links' => $links)),
'centerContent' => new Template('homeView.php', array('date' => date())),
));
$main->render();
mainView.php
<html>
<head>
<title><?= $this->title; ?><title/>
</head>
<body>
<div id='left'><? $this->leftMenu->render(); ?></div>
<div id='center'><? $this->centerContent->render(); ?></div>
</body>
</html>
Below are minimal template classes for both php 4 and 5.
// PHP 4
class Template {
var $args;
var $file;
function Template($file, $args = array()) {
$this->file = $file;
$this->args = $args;
}
function render() {
extract($this->args);
include $this->file;
}
}
// PHP 5
class Template {
private $args;
private $file;
public function __get($name) {
return $this->args[$name];
}
public function __construct($file, $args = array()) {
$this->file = $file;
$this->args = $args;
}
public function render() {
include $this->file;
}
}
PHP itself was born as a template language with a scripting capabilities. Using Smarty or any other template language means running an interpreted language on top of an interpreted language, which doesn't sound like a good idea if you think about it. At the end of the day, Smarty templates are still "compiled" to PHP code (which is sometimes ineffective and always unreadable), so it might be wiser to just use PHP and not to learn another language.
Starting there, one should limit the "HTML code" to echo(), basic loops and conditionals, strengthtened maybe with function calls with no side-effects. Calculating MD5 hash inside HTML template to get a link to gravatar image is ok, executing some SQL is not. All data to be rendered inside PHP templates should already be prepared by another module, unless it is trivial to get inside your "view" part.
The MVC pattern is a good way of thinking about your code. A framework, such as CakePHP, could offer a powerful platform to build on, and provide some hints on organizing code if all its complexity is an overkill for your task.
In my opinion, Smarty's over-complexity defeats the point in separating the logic. Most people abuse Smarty and just treat it as PHP. If you really want to make life easier, use a templating system that is limited to just conditionals and loops. It's all you need in reality.
Rather than try to seperate your php and html you should instead be separating your backend logic and display logic.
A templating system requires people to learn its syntax so why not just use php for it
From my point of view you are asking the wrong question, the question should be: ¿How do I separate my Business Logic from the Presentation?
And the answer is, use a Model-View-Controller Framework (or make your own architecture around this concept).
Use PHP strong Object support and make nice classes that obtain data from your database, this classes should also handle the saving of this same data. This classes are called "Models".
Make a nice class that handle the loading of a template (might be a simple "include template.php" or a full smarty [1] implementation). The template should only do conditionals and loops. This is the "View"
You still need a third element, a php file that will load the model and will send the data to the view and viceversa (this is where the nasty code usually lives), is called the "Controller"
The idea is to create reusable components, you can make your own basic MVC architecture or use one of the nice Frameworks out there like Zend's or Cake PHP.
The basic idea is that if you just split PHP and HTML, you are only splitting the mess in two bedrooms, leaving the corridor with much bigger mess.
Think like a store, you have your front that display products(usually in a very creative way), a business man in the middle handling clients, and a store room in the back with everything really really ordered.
[1] http://www.smarty.net/I tend to like Smarty. It's clean, at the cost of a few CPU cycles.
Rasmus Lerdorf, creator of PHP, has posted some slides from a presentation titled " Simple is Hard [1]." Starting on slide 24 [2], he compares static HTML and basic inline PHP to a number of PHP frameworks. Makes one want to try inline PHP again. Template syntax can be approximated in straight PHP while staying reasonably readable:
<html>
<head>
<title><?php echo $template->title; ?></title>
</head>
<body>
<?php foreach($items as $item): ?>
<h2><?php echo $item->title; ?></h2>
<div class="content">
<?php echo $item->content; ?>
</div>
<?php endforeach; ?>
</body>
</html>
Using auto_prepend_value [3] in your .htaccess can automate inclusion of your initialization script, which has the potential to reduce extraneous PHP in your "template." Definitely lots of ways to remove business logic from your HTML pages.
[1] http://talks.php.net/show/drupal08/htmlspecialchars
:) - Timo Huovinen
What I have done in the past is to generate all the data for a page and store in hash array:
$data['#title#'] = 'Page title';
$data['#textcontent#'] = ' Yadda yadda yadda';
Grab a seperate bit of text that is the HTML with placeholders in it:
$html = '<html>
<head>
<title>#title#</title>
</head>
<body><p>#textcontent#</p>
</body>
</html>'; // etc
Then merge the two with a simple command:
$html = str_replace(array_keys($data),array_values($data),$html);
The print or store in cache.
#newstitle#
and corresponding HTML 20 times as well? - Your Common Sense
Remember that despite the constant dogma about keeping business logic and presentation separate, there is such a thing as presentational logic.
Don't be afraid to use inline PHP logic for tasks like sorting and arranging data for display on the page. If your "business logic" modules are full of helper functions with little bits of presentational logic, you are doing it just as wrong as if you were spewing out business logic in the middle of the templates.
Be suspicious of 'advanced' templating languages that limit you to outputting simple attributes using a microlanguage, instead of letting you use the full power of PHP. This is inflexible dogma which only constrains you; you will end up polluting your business logic with presentational concerns that the templating language won't let you express. You can do perfectly good 'readable' templates with PHP as long as you use it tastefully - for example see the example posted by Adam Backstrom for a good way of keeping track of your structures using indentation.
(Unfortunately, that example - along with every other one posted here so far - is full of the HTML-injection security holes that PHP is so famous for. Any time you output a bunch of normal text into an HTML page, you must use htmlspecialchars! One way to make this slightly less onerous is to define a function that does echo(htmlspecialchars($s)) and call it something nice and short like 'h', so that you can put:
<?php h($item->title) ?>
in the template.)
Personally, I live by the "conditionals and loops" rule: my HTML can contain only conditionals and loops in PHP code. This is a subjective rule, obviously, but it's a good principle. You can use PHP to format your HTML (to display a table row for every item in an array or to display a user's login name, for instance) and still keep your business logic completely separate.
However, if you're not happy with that, there's a host of possible solutions, including Smarty or XSL (might be overkill, depending on what you're doing).
Template systems such as Smarty [1] are a good way to go.
If this is overkill for your particular project, then the best solution is to separate the PHP logic and HTML presentation code into separate files, including the PHP files in your HTML, e.g.
index.php:
<?php
include("user_functions.php");
$user_data = get_user_data();
?>
<html>
<body>
<?php
foreach($user_data as $user)
{
echo "User: ".$user."<br />";
?>
user_functions.php:
<?php
function get_user_data()
{
...
}
?>
There is still some cross-over between PHP and the HTML, but it's at a minimum, and makes maintenance of the PHP functions much easier when you're not rooting through layers of HTML to get at it.
[1] http://www.smarty.net/Best practices for software development call for a full separation of business and display logic.
This particularly applies if you are building a large scale web application (even more so if you wish to release that application as a product and have your users/customers tailor it).
As noted by others, PHP was originally designed to be a templating system, but has evolved into a rich complex object oriented development language.
As a result, the best way to split your true presentation code from your business logic is to use a templating engine.
There are many of these.
Smarty [1] is a popular and long-standing templating engine, which is somewhat "Pushing the boundries" and getting closer to PHP (i.e. becoming a language in it's own right). The Zend Framework [2] includes it's own templating engine which takes a pure PHP5 OO approach using PHP as the formatting language in templates. And the SimpleT [3] template takes a very light weight PHP4 approach to using PHP as a templating engine. There are other engines around such as PEAR's HTML Template Flexy [4] class which provide a less "language like" templating engine.
The right choice for your application will depend on what you are doing, always remembering that the right choice might be no templating class but simply performing the logic in one code block followed by a full "template" of HTML populated with loops and variables in the next part of the file. If it's a small application with a limited lifespan, the saving in effort doing this in the short term may pay off against the larger effort required to fully implement templating.
[1] http://smarty.php.netYou must use MVC (model-view-controller) pattern [1].
[1] http://en.wikipedia.org/wiki/Model-view-controllerUse an application framework like Zend [1], CakePHP [2], Symfony [3] or CodeIgniter [4]. These make it possible to divide your application into controllers and views, where the controllers are the code that retrieves the data you want to display and the views are what renders that data to HTML. The views contain a minimal amount of code. Some of the frameworks have a special templating language for conditionals and loops in the views, others just use PHP, but all are focused on keeping the amount of code in the views to a minimum.
[1] http://framework.zend.com/Smart is well respected but many people think implementing a macro language in the templates negates one of the main reasons for using a template system - separation of code and html. I would tend to agree with that and instead would point you at Tiny But Strong (www.tinybutstrong.com).
IMHO the great joy and strength of TBS is it is completely Dreamweaver compatible so if you use that templates can be designed WYSIWYG. If you're working with a designer or uses Dreamweaver (or you do yourself) TBS scores massively as they can be up and running modifying your basic templates within 5 or 10 minutes. Smarty breaks the WYSIWYG model so your designer (or you) has to learn that too and visualize what the clean html looks like instead of seeing it.
TBS doesn't come with an AJAX library, but it's relatively easy to add one (XAJAX works nicely) and ditto for whatever Javascript library/framework you'd like too. It also enforces a very simple, discrete, code/template model which fans of Zend and the like will look down on, but for 95% of websites this is a positive plus as this modularity pays off in ease of maintenance.
If you use REST techniques - so that POST requests do work and then send the browser a 303 redirect to GET to view the results, you quickly achieve two things:
The browser back button behaves itself - no more duplicated actions.
Your business logic and views get nicely separated.
Personally I found the way that works for me is to work with XSL Transformations (XSLT) [1].
Have one script containing your (PHP) logic outputting XML and one script produce the XSL to translate the XML to something visible. I usually implement this all on top of a homemade rewrite of Fusebox [2] (the rewrite is purely because I don't use most of the features Fusebox offers and they do create overhead).
This might seem like a bit of overkill, especially on smaller projects, but I noticed a huge increase in the speed with which I can make modifications. Let's just say that my boss was pleased.
Imagine having the following information in an array, which you want to display in a table.
Array
{
[car] => green
[bike] => red
}
You easily create a script that outputs this information in XML:
echo "<VEHICLES>\n";
foreach(array_keys($aVehicles) as $sVehicle)
echo "\t<VEHICLE>".$sVehicle."</NAME><COLOR>".$aVehicles[$sVehicle]."</COLOR></VEHICLE>\n";
echo "</VEHICLES>\n";
Resulting in the following XML:
<VEHICLES>
<VEHICLE>
<NAME>car</NAME>
<COLOR>green</COLOR>
</VEHICLE>
<VEHICLE>
<NAME>bike</NAME>
<COLOR>red</COLOR>
</VEHICLE>
</VEHICLES>
Now this is all excellent, but that won't display in a nice format. This is where XSLT comes in. With some simple code, you can transform this into a table:
<xsl:template match="VEHICLES">
<TABLE>
<xsl:apply-templates select="VEHICLE">
</TABLE>
</xsl:template>
<xsl:template match="VEHICLE">
<TR>
<TD><xsl:value-of select="NAME"></TD>
<TD><xsl:value-of select="COLOR"></TD>
</TR>
</xsl:template>
Et voila, you have:
<TABLE>
<TR>
<TD>car</TD>
<TD>green</TD>
</TR>
<TR>
<TD>bike</TD>
<TD>red</TD>
</TR>
</TABLE>
Now for this simple example, this is a bit of overkill; but for complex structures in big projects, this is an absolute way to keep your scripting logic away from your markup.
[1] http://www.w3.org/TR/xsltSeparating your code into MVC should NOT be an automatic first step. There are many cases where a simple procedural framework makes much more sense.
I agree with @AdamBackstrom that inline PHP is simpler and more effective than placing one templating system (such as Smarty) on top of another templating system (PHP). If you don't take advantage of PHP's existing templating system, why are you using the language at all?
I like to use alternate syntax when working with html. For example:
<div class="profile-header">
<div class="left">Blog</div>
<?php if($profile_data['userid']==$userid):?>
(<a href="/<?=strtolower($profile_data['username']);?>/edit/blog">New Blog Post</a>)
<?php else:?>
(<a href="/rss/<?=strtolower($profile_data['username']);?>/">RSS Feed</a>)
<?php endif;?>
</div>
It really does help keep the code clean, and to a designer, it shouldn't be too hard to pick up. not only that, but it's similar to the way Wordpress templates work.
A good MVC framework that I have come across is Kohana [1] It is simple to use and easily extensible. Doesn't require any server side includes.
I will be using it in one of my web projects.
[1] http://kohanaphp.com/homeYou can use a template system like Smarty [1] or you could use a framework like CakePHP [2].
[1] http://www.smarty.net/@[levhita]:
At the end of the day, the Presentation or View part of a project must have some form of code or templating system in it, as there is variables that need to be outputted, template files to be included, etc etc etc.
Perhaps the question should then be what code and how much code is allowed in the Presentation / View part of a framework / project.
It's good practice to separate you data model, your business logic, and your presentation layer. The most popular and talked about way to do that is to use and Model-View-Controller (MVC) [1] design pattern. There are other design patterns such as the Presentation-Abstraction-Control (PAC) [2] design pattern. While this pattern is not as widely talked about it is regularly used.
Most of the frameworks and content management systems use some form of this right now. If you start digging through the code of systems like symfony, cakephp, drupal, joomla, and others you'll see these types of systems in action.
[1] http://www.dossier-andreas.net/software_architecture/mvc.htmlMy way of doings is the same as described above. Add inbetween is the easiest. And if I need to insert things into a snippet of code I create multiline variables with placeholdes that I replace later.
<?php
$snippetCode = <<<html
<a href="%URL%" alt="%ALT%">%TEXT%</a>
html;
echo str_replace(array('%URL%','%ALT%','%TEXT%'),array('http://stackoverflow.com', 'Stack Overflow', 'This way to Stack Sverflow'),$snippetCode);
?>
I agree with the answers here suggesting that you avoid using anything besides PHP for templating. And of course, there is such a thing as presentation or display logic. That said ...
You can separate your PHP and HTML into separate files -- putting HTML files into a views or templates directory -- depending on how you want to set things up. If you do it this way, the last line of any PHP script using that template or view can just be an include statement.
If you keep things in the same file, that can work too, if the project isn't too complicated. In this case, instead of an include statement, you'd have two chunks of stuff, PHP to start and HTML to follow.
Of course, you will need to pepper your HTML with echos, and sometimes you will need some logic right there along side your HTML, but try to keep it to a minimum. There's often no way around it when you are presenting results, say, from multiple rows in a database. Sometimes you can put the WHILE chunk in a nested sub-template.
One thing is don't echo HTML with PHP. Yuck. You will regret this.
I try to avoid using curly braces around chunks of HTML too. Not always feasible, but a good rule to follow.
The truth is that html is extremely simple. Another truth is that nothing is free. Using complex templating system will increase your development time. You should use the simplest route. Sometimes that will be no templating at all(in a case of 2 or 3 pages). Sometimes a splitting the page into header.php, footer.php and content.php will be enough. In case of a huge program with multiple teams, a templating platform will be the way to go. The problem comes when you dont choose the right solution for your project size. There is no silver bullet. Web pages are flexible, they can be anything. Is not like when you code a windows program, where the widgets are predifined. So you cannot expect that any template engine will solve all your problems. You will always, sooner o later, mix php and html. Just live with it. I dont see anything wrong. If you ever change the look of your site, you must likely added functionality and code was to be revisited anyway.
PConroy's is a good answer - also make extensive use of CSS so that those elements are kept separate.
Back in the days when PHP4 was cutting edge, PHPlib's templating system served me well. It is simple to setup and really easy to use for basic things. See some examples [1] here.
It is a bit old but it is stable and simple.
[1] http://www.sanisoft.com/phplib/manual/TemplateExamples.phpThe best way to separate PHP Code and HTML is to follow MVC pattern. Adopting one of the PHP frameworks like Zend [1] or CakePHP [2] would be a good start. Using one of these frameworks would save you countless development hours and help you focus on meeting the business needs of the project.
[1] http://framework.zend.com/You can write your own basic template system with something like:
function Render($Template, $Data) {
extract($Data);
include($Template);
}
Extract() is used to create local variables from an associative array that can be used in template file. You could also automatically escape your data.
In your template file you can use <?= $Foo ?>
to render a variable. Short tags are not portable but you can use your favorite build tool to replace <?=
to <?php echo
before deploying your application.
For loops and conditions, your can use the alternative syntax:
<? if ($Foo): ?>
...
<? endif; ?>
Like levhita, I think you're asking the wrong question. There's nothing fundamentally wrong with mixing HTML code with your PHP code. In fact, it's usually difficult to get around. Even using an MVC framework, there's often a need to mix the two. When iterating over a set of values to be output, for example. To do that, you either create an HTML in your controller (awkward) or include presentation logic in your view. In my opinion, including presentation logic in your view is perfectly acceptable. It is, after all, presentation logic and not business logic.
If your distaste is aesthetic, then try the alternate syntax. I prefer than when mixing tag-based markup with PHP. It just looks cleaner and I find it easier to read.
Write your own templating object or use one like Savant [1], my personal favorite. Do not use another templating language. While PHP is much more than a templating language, it is still excellent for templates. All you really need is an object that defines a scope for the template so it only has access to the variables and objects you pass to it.
Here's the simplest possible class for your views that will accomplish this:
class View {
protected static $VIEW_PATH = '/wherever/your/views/are/';
public function assign($name, $value) {
return $this->$name = $value;
}
public function render($filename) {
$filename = self::$VIEW_PATH . $filename;
if (is_file($filename)) {
ob_start();
include($filename);
return ob_get_close();
}
}
}
(Obviously, there's a lot more you can do, like error handling for missing views.)
Choose a set of rules to follow for your views. Here are mine:
I'll echo the concept of separating what's done in a 'template' instead of using an entirely different template 'language'. After using a few different template systems (including smarty and flexy), I've found just using inline php (using the Zend MCV system) very refreshing. Inline PHP really is a good templating language, and I don't have to keep thinking, "what's the smarty foreach syntax?"
Of course, then it's up to you to make sure the templates are only templates. It also up to you to determine where you draw that line. Personally, I'm okay with the template formatting data (like a timestamp), while others may only want the template to handle conditionals and loops. But when someone starts throwing SQL in the template, I think they've missed the point.
I think a good idea is to use these functions: file_get_contents() explode() printf()
Suppose I want to display this table:
Number Square(number)
1 1
2 4
...
I create Tmpl.html file with this content
<html> <body> <table> <tr> <td> Number </td> <td> Square(Number) </td> </tr>
<!-- Break --> <tr> <td> %s </td> <td> %s </td> </tr> <!-- Break -->
</table> </body> </html>
I wrote the php script
<?php
$T = file_get_contents('Tmpl.html');
list($A, $B, $C) = explode($T, '<!-- Break -->');
printf($A);
for ($i=1; $i<=10; $i++)
printf($B,$i,$i*i);
printf($C);
?>
I love the Text::Template [1] module for perl and html. It allows me to keep my html independent from my logic and I can use Dreamweaver to continually maintain the html design.
Text::Template [2] is a more elegant and simpler solution than the smarty philosophy.
Unfortunately, I haven't found a direct counterpart for perl's text::template in php yet.
[1] http://search.cpan.org/dist/Text-Template/lib/Text/Template.pmUse XSL instead of a templating system. Most templating systems combine PHP code and HTML in the same file. This means that even with lots of discipline, you are still going to put PHP and HTML together. If you use XSL, you'll never run into this problem. XSL gives you variables and conditionals and looping, in case you should need such constructs.
The other great thing about this approach is that if you ever decide to change the backend language (PHP to Ruby or Java, for instance), the front-end XML/XSL code never has to change. If you don't go around changing backend languages often, think about another scenario: one in which the back-end might be coded in two different languages for certain tasks. By keeping the view consistent in XSL, I think you've made your life that much easier.
Templating systems like Smarty and Zend are better than straight PHP when you want a common page layout over many separate pages, or want reusable chunks of parameterized content to appear in many pages. However you do it, the HTML/template files should be well-formed HTML that you can view and edit with HTML tools like Dreamweaver.
function template($fn) {
return "echo <<<END\n".str_replace(array(''), array("END;\n", "echo <<<END\n"), file_get_contents($fn))."\nEND;\n";
}
Then you can create templates like example.tpl that would contain "hello $what" and render that template from code like so:
$what = "world"
eval(template('example.tpl'));
And it displays "hello world".
Use a clientside templating system (like Chain http://javascriptly.com/2008/08/a-better-javascript-template-engine/ ). Your templates will be plain simple HTML and you can fetch all your data from your server using JSON; you can use PHP serverside to just do business logic (no templating).
-- MV
One of the things about php being coupled with html is that together they make a very quick development language and php does what does reasonably well, however, if you're looking to do a small project using a templating system is a bit overkill.
The languages are so tightly couple that it doesn't really make sense to seperate them too much. Too much seperation and you lose the maintainability in terms of debugging simple errors in one system or the other. Too little and like you say you have the problem of code being hard to read. At the end of the day you have to find what works best for you, are you going to be happiest dealing with a little bit of a cross between .php files containing html or do you not wantt o have to look at html at all whilst doing php and visa versa? (the latter being very difficult to achieve imo)
Check out this article: Template Engines [1]
[1] http://www.massassi.com/php/articles/template_engines/Like Lucas Oman's answer. I am actually wondering the same thing as I am now getting into Classic ASP. Mixing the code and the HTML just seems like an ugly mess and difficult to maintain. So it seems like the best suggestions so far are:
MVC
Smarty
XSLT
Zend
There is going to be alot of debate here as PHP works both for people coming from the Comp Sci Camp and people coming from the designer that learned HTML camp. Both are going to want to create their sites differently.
For most PHP code, a strict MVC split is 10x more abstraction then necessary. A major annoyance. Simple templating (basic conditional and loops) is perfectly adequate and much simpler to implement. Leave the heavy duty MVC frameworks to consultants milking large Java projects for all the dollars they can.
Obviously, if you're a consultant and paid by the hour, please maximize the size of your framework, it'll maximize your bottom line too. Client be damned.
I realize that project XYZ absolutely needed MVC to even be comprehensible by mere mortals, but why was it coded in PHP?
I like to have my php file such as "recipe.php" and then it handles the different actions concerning that page (ie. view, create, list) in the logic. After it decides which path to go down, it "includes" the correct html code which is stored in something like ./html/recipe.view.php or whatever. This allows you to handle a lot of different actions within a single "page" without a ton of clutter. You can still use php inside your html "template" so its very usable as well. I think people over complicate things waaay too much and I've found that this method works very well, especially for fairly simple sites.
I really like the HAML [1] syntax. I've played around with phpHaml [2], and so far I like it a lot. There's also another implementation of HAML in PHP called Phammable [3], but i haven't tried that one yet.
If you're building a large project i would recommend you to look at the MVC paradigm, either writing your own implementation of it or look at some of the open source ones.
[1] http://haml.hamptoncatlin.com/Use OO PHP. It helps a lot especially when you use HTML forms. That way you minimize the HTML in the code and make it more readable and structured.
You can use the "Smarty" template engine to sepatate the HTML and PHP code.
Its easier to apply all the css styles to the html files, keeping it separate from the PHP code.