Todo mundo que programa em PHP sente falta de uma boa alternativa para separar o código PHP do visual (HTML). Nessas horas vale a pena estudar algumas template engines para PHP disponíveis para saber qual que melhor se adapta à suas necessidades e projeto. Alguns frameworks MVC possuem sua própria engine, outros tentam.

Smarty

O mais famoso e usado como inspiração por muitos outros projetos. Robusto (possuindo blocos condicionais/loops e várias funções próprias) e rápido (“compilando” suas páginas para arquivos PHP).

    <ul>
    {foreach from=$myArray item=foo}
        <li>{$foo}</li>
    {/foreach}
    </ul>
$smarty = new Smarty;
$arr = array(1000, 1001, 1002);
$smarty->assign ('myArray', $arr);
$smarty->display ('HelloWorld.tpl');

vlibtemplate

Com esta engine saímos de um problema e entramos em outro, é necessário aprender (lembrar) algumas palavras reservadas para sinalizar variáveis, além do uso dos limitadores das expressões.

<html>
    <head>
        <title>{tmpl_var name='title_text'}</title>
        <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    </head>
    <body>
        <p>{tmpl_var name='body_text'}</p>
    </body>
</html>
$tmpl = new vlibTemplate('tmpl/basic.htm');
$tmpl->setvar('title_text', 'TITLE: This is the vLIB basic example ...');
$tmpl->setvar('body_text', 'BODY: This is the message set using setvar()');
$tmpl->pparse();

FXL Template

Muito pouco usual, o FXL faz uso dos blocos de comentário HTML para definir os loops. Outros semelhantes e nada melhores são: QuickSkin e XTemplate.

 <table>
     <!-- START row -->
         <tr>
             <!-- START cell --> 
             <td >{td_value} </td> 
             <!-- END cell -->
         </tr>
     <!-- END row -->
 </table>
$fxlt = new fxl_template('example.tpl');
$fxlt_row = $fxlt->get_block('row');
$fxlt_cell = $fxlt_row->get_block('cell');
for ($tr = 1; $tr <= 3; $tr++) {
    for ($td = 1; $td <= 3; $td++) {
        $fxlt_cell->assign('td_value', $tr.':'.$td);
        $fxlt_row->assign('cell', $fxlt_cell);
        $fxlt_cell->clear();
    }
    $fxlt->assign('row', $fxlt_row);
    $fxlt_row->clear();
}
$fxlt->display();

Vemplator

Mais do mesmo, mas com alterações de sintaxe.

<h1>{if:logged} Welcome {username} {else:} User not logged {end:} </h1>
<ul>
    {foreach:rows,row}
        <li>
        {row['name']} 
        </li>
    {end:} 
</ul>
$t = new vemplator();
// if/else
$t->assign('logged', true);
$t->assign('username', 'Rogerio');
// loop
$items = array(
	array('name' => 'Laptop'),
	array('name' => 'Memory Stick')
);
$t->assign('rows', $rows);
echo $t->output('example.template.html');

TinyButStrong

Uma alternativa ao estilo Smarty de muitos, porém é mais confuso e segue um padrão de nomenclatura bem particular.

<table>
    <tr><td>[blk.val;block=tr]</td></tr>
</table>
$TBS =& new clsTinyButStrong ;
$TBS->LoadTemplate('template.htm') ;
$list = array('X','Y','Z') ;
$TBS->MergeBlock('blk',$list) ;
$TBS->Show();

Dwoo

Possui como diferencial um Template Inheritance, o que facilita muito a vida na construção de templates.

<html>
    <head>
        <title>{block "title"}My site name{/block} </title>
    </head>
    <body>
        <h1>{block "page-title"}Default page title{/block} </h1>
        <div id="content">
        {block "content"}
            Welcome to my amazing homepage
        {/block}
        </div>
    </body>
</html>
{extends "base.html"}

{block "title"}
    Gallery
{/block}

{foreach $images img}
    <img src="{$img.url}" alt="{$img.description}"></img>
{/foreach}
$dwoo = Dwoo();
$images = array(
    array('url' => 'img1.jpg', 'description' => 'Ferrari'),
    array('url' => 'img2.jpg', 'description' => 'BMW')
);
$params = array();
$params['images'] = $images;
echo $dwoo->get("gallery.tpl", $params);

h2o

Baseado no Smarty, Django Templates e Jinja (os dois últimos para Python).

<html>
    <head>
        <title>{{ page.title }}</title>
    </head>
    <body>
        {{ page.content }}
    </body>
</html>
$h2o = new h2o('index.html');
$page = array(
  'title' => 'title of a page',
  'body' => 'Hello world'
);
echo $h2o->render(compact('page'));

PEAR Flexy

Entre os projetos disponíveis no PEAR (PHPLIB, Sigma e IT) esse é o melhor.

Tem como desvantagem o fato de ter que definir as propriedades da sua classe como public (pelo menos dá para trabalhar com classes), linhas de includes e configurações exageradas (não presentes no exemplo abaixo), e algumas automações que precisam ser bem explicadas senão o programador (usuário) fica doido. Além de ter que codificar muito mais linhas se compararmos com os demais exemplos.

<html>
    <head>
        <title>{title}</title>
    </head>
    <body>
        <!-- o valor do input será adicionado em $element['input'] -->
        Input Box: <input name="input" />
        <ul>
            <!-- isso é o mesmo que foreach ($numbers as $number => $string) -->
            <li flexy:foreach="numbers,number,string" >
                <a href="mypage.html?id={number}">{string}</a>
            </li>
        </ul>
        <!-- chamando o método da classe -->
        {someMethod()}
    </body>
</html>
class controller_test  {

    var $title;
    var $numbers = array();
    var $elements = array();

    function controller_test() {
        $this->start();
        $this->output();
    }

    function start() {
        $this->title = "Hello World";
        // create an HTML Element for the form element.
        $this->elements['input'] = new HTML_Template_Flexy_Element;
        $this->elements['input']->setValue('Hello');

        for ($i = 1;$i< 5;$i++) {
            $this->numbers[$i] = "Number $i";
        }
    }

    function output() {
        $output = new HTML_Template_Flexy();
        $output->compile("home.html");
        $output->outputObject($this,$this->elements);
    }

    function someMethod() {
        return "Hello From A Method";
    }

}
new controller_test();

Todos os exemplos a cima foram retirados dos próprios sites dos projetos, sofrendo alterações afim de minimizar as linhas e focar em suas caracterísicas, vantagens e desvantagens.

Em meados do ano passado comecei escrever uma engine baseada no JSF+Facelets (Java) e nesse mês voltei a trabalhar nela e espero que no próximo ano (2011) já tenha uma versão liberada (farei um post sobre).