Back-End

13 mai, 2009

16 técnicas smarty scripting para deixar seus templates ainda mais inteligentes

Publicidade

Uma compilação de dicas e técnicas muito úteis para se programar em
Smarty Template Engine e construir dinâmicos e inteligentes templates
para programadores PHP e designers de templates. Uma ótima fonte para
quem está começando a codificar Smarty Templates. Tenho certeza que
economizará muito tempo de procura.

1. Re-utilização de código HTML

Utilize a tag {caption} para gravar dentro de uma variável qualquer saída de html que estiver entre o {caption} e o {/caption}. É muito útil quando queremos re-utilizar o mesmo código em vários pontos do nosso template.

No exemplo abaixo estamos atribuindo toda a saída HTML para a variável $nav:

{capture name='nav'}
<ul>
{section name=item loop=$nav}
<li><a href="{$nav[item].url}" title="{$nav[item].title}">{$nav[item].label}</a></li>
{/section}
</ul>
{/capture}

Mostra o conteúdo da caption $nav:

{$smarty.capture.nav}

Você pode também setar a saída da caption para uma variável de template:

{capture name='nav' assign='navmenu'}

Para exibir:

{$navmenu}

Quando o “name” não é especificado, o nome da caption automaticamente é setado como “default”:

{$smarty.capture.default}

2. Passando variáveis para sub-templates

Usando $GLOBALS via {php}, para nós, programadores, resolve o problema, certo? Mas é recomendado pelos designers de template que vocês utilizem o {capture}.
Os designers de templates não querem colocar as suas mãos em código
PHP, então, vamos falar em uma linguagem que eles também entendam.

Arquivo header.tpl

{capture name='columns'}3{/capture}

Então, arquivo index.tpl

{include file='header.tpl'}
{if $smarty.capture.columns == '3'}
. . .
{/if}
{include file='footer.tpl'}

Pode até mesmo acessar a variável dentro do footer.tpl

{if $smarty.capture.columns == '3'}
. . .
{/if}

3. Incluindo sub-templates utilizando delimitadores padrão

Aqui temos um problema comum quando queremos inserir variáveis de
template dentro de arquivos javascript ou CSS. o Delimitador { e } é
utilizado por ambas linguagens, então, vamos ter conflitos.

main.tpl

{php}
$smarty = new Smarty;
$smarty->left_delimiter = '<!--{';
$smarty->right_delimiter = '}-->';
$smarty->assign('size', '36px');
$smarty->assign('pre', 'Great');
$smarty->assign('post', 'Templates');
$smarty->display(message.tpl');
{/php}

message.tpl

<style type="text/css">
<!--
h2 {font-size: <!--{$size}-->}
-->
</style>
<h2>Welcome to the World of <!--{$pre|capitalize}--> Smarty <!--{$post|capitalize}--></h2>
<script language="javascript" type="text/javascript" >
<!--
function welcome(){
alert('Welcome to the World of <!--{$pre|capitalize}--> Smarty <!--{$post|capitalize}-->');
}
welcome();
-->
</script>

O código acima mostra o texto “Welcome to the World of Great Smarty
Templates” com uma fonte de tamanho 26px e alerts com o mesmo texto.

4. Debugando Smarty Templates

O Smarty tem um console para debug que permite que você facilmente
examine variáveis de template, templates incluídos, e variáveis de
configuração para o template atual.

Para ativar o console de debug, defina a propriedade $debugging do smarty como true:

<?php
$smarty = new Smarty;
$smarty->debugging = true;
...
?>

Se a janela do debug console não abrir quando a página for carregada, sete a propriedade $debug_tpl para o seu caminho path. Por padrão, Smarty vai olhar para o “debug.tpl” no SMARTY_DIR. Este arquivo é incluído nas distribuições do Smarty e pode ser achado na pasta “libs/”.

O jeito mais fácil e mais rápido para habilitar o debugging console é colocando a tag {debug}
nos seus templates. Funciona da mesma forma. No entanto, Isso só
permite visualizar todas as variáveis disponíveis dentro do escopo do
template atual.

Exemplo:

<h1>{$title}</h1>
{debug}
<p>{$description}</p>

5. Acessando Request Variables via Smarty Templates

Request Variables do PHP podem ser acessadas via templates Smarty,
utilizando a variável reservada {$smarty}. Request Variables, incluindo
$_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, e $_SESSION.

Exemplos:
Valor de saída da variável $_GET[‘page’] da URL

{$smarty.get.page}

Valor de saída da variável $_POST[‘page’] do formulário

{$smarty.post.page}

Saída de uma variável de cookie, $_COOKIE[‘status’]

{$smarty.cookie.status}

Saída de uma variável de servidor, $_SERVER[‘SERVER_NAME’]

{$smarty.server.SERVER_NAME}

Saída de uma variável do ambiente do seu sistema, $_ENV[‘PATH’]

{$smarty.env.PATH}

Saída de uma variável de sessão, $_SESSION[‘id’]

{$smarty.session.id}

Saída da variável “username” de todos os arrays juntos (get/post/cookies/server/env)

{$smarty.request.username}

6. Acessando variáveis de templates via script PHP

Você consegue acessar variáveis do smarty utilizando o método get_template_vars()
no seus scripts PHP. No entanto, as variáveis de template só estão
disponíveis depois do tempo de execução e interpretação dos seus
templates. Depois deste trabalho, as variáveis são diretamente
incorporadas para serem acessadas via PHP utilizando a tag {php} ou incluindo um arquivo php utilizando uma tag de função built-in {include_php}.

Considere o seguinte template:

{assign var='title' value='Smarty Templates'}

Acessando as variáveis depois da execução do template:

// Executa o template e retorna o resultado para uma variável
$page = $smarty->fetch('index.tpl');

// Vai mostrar "Smarty Templates"
echo $smarty->get_template_vars('title');

// Assina um valor para a variável title
$smarty->assign('title', 'The Great Smarty Templates');

// Vai mostrar "The Great Smarty Templates"
echo $smarty->get_template_vars('title');

// Vai exibir todas as variáveis assinadas dentro do template
var_dump($smarty->get_template_vars());

Existem dois jeitos de acessar variáveis de tamplate durante a execução do template utilizando a tag {php}:

{php}
// using $this->_tpl_vars
echo $this->_tpl_vars['title'];

// using $this->get_template_vars() method
// the variable $this, is a smarty object
echo $this->get_template_vars('title');
{/php}

7. Substituição de variaveis em strings com aspas duplas

Funciona muito parecido com o jeito que você faz em PHP quando
existem variáveis dentro de aspas duplas e exibir os seus respectivos
valores dentro dentro destas aspas.

Substituição simples

Com o $filename tendo o valor “footer”, o atributo file vai apresentar o valor “templates/footer.tpl”.

{include file="templates/$filename.tpl"}

O código acima não funciona com aspas simples:

{include file='templates/$filename.tpl'}

Array Indexes

Assumindo que $module[1] contém “user_menu”:

O $module[1] acima vai ser substituído por “user_menu” e será traduzido dentro de “user_menu.tpl”.

{include file="$module[1].tpl"}

Com o valor de $index igual a 1, o código abaixo vai fazer algo parecido com o código de acima. Neste caso anexo a backticks.

{include file="`$module[$index]`.tpl"}

Associative Arrays

Assumindo que $item[‘name’] seja igual a “Computer”:

A variável $item.name abaixo vai ser substituido de “Computer” para “Computer unit”.

{assign var='label' value="`$item.name` unit"}

Com o valor de $prop igual a “name”, o que temos a seguir é equivalente ao código anterior.

{assign var='label' value="`$item.$prop` unit"}

Objects

Temos uma propriedade dentro de um objeto chamada $book->title que contém “Smarty Templates”.

O $book->title acima vai assumir o valor de “Smarty Templates” mas $msg tem o valor “My Smarty Templates book”.

{assign var='msg' value="My `$book->title` book"}

Com a $property igual a “title”, $msg vai apresentar o mesmo valor.

{assign var='name' value="`$book->$property`"}

Nota: Sempre anexe nomes de variáveis com (`)
quando elas conterem pontos (.), objetos por referência (->), ou
quando usarem index variables para arrays.

8. Manuseando variáveis de template em branco

Variáveis em branco podem quebrar o layout da sua tabela. Variáveis
com valores em branco podem ser um problema em muitos casos, por
exemplo, se alguma imagem do seu layout vier de uma variável de
template, imagine esta imagem recebendo o src em branco toda vez que
alguém acessa sua página? Muitas requisições perdidas, sem motivo?

Use a tag {if} para gerar uma saída padrão sempre que uma variável estiver em branco. Ou use o atalho, A variável modificadora “default”.

Considerando o código a seguir, exibirá dentro da célula de uma tabela:

<table><tr><td>
{if $user eq ''}
&nbsp;
{else}
{$user}
{/if}
</td></tr></table>

O shortcut:

<table><tr><td>{$user|default:'&nbsp;'}</td></tr></table>

Esse é o código que maniputa a propriedade src do img:

<img src="{if $image_url eq ''}/images/default.png{else}{$image_url}{/if}" />

Ou simplesmente:

<img src="{$image_url|default:'/images/default.png'}" />

O shortcut pode ser bem limpo olhando assim, somente neste tutorial,
mas se você tiver o hábito de usar SEMPRE nos seus templates, ao longo
do tempo isso pode ser meio “feio” de ser ver.

Por exemplo, considerando o código abaixo:

<a href="{$image_url|default:'/images/default.png'}">
<img src="{$image_url|default:'/images/default.png'}" />
</a>
<p>Path: {$image_url|default:'/images/default.png'}</p>

E, finalmente, aqui está um método bem mais limpo utilizando a tag {assign} com default.

{assign var='image_url' value=$image_url|default:'/images/default.png'}
<a href="{$image_url}">
<img src="{$image_url}" />
</a>
<p>Path: {$image_url}</p>

9. Passando variáveis para sub-templates

É muito comum para os web developers e web designers colocarem conteúdos repetitivos em templates separados e {include}
(incluir) eles como necessários. Um exemplo típico é o header.tpl que
inclui a tag html title etc. Suponhamos que precisaremos dele para
exibir diferentes títulos em diferentes paginas dependendo da página
que é incluída. Você consegue fazer isso, utilizando o atributo “title” da tag {include}, e é assim que passamos variáveis para sub-templates no Smarty.

Exemplo de tamplate que inclui o header.tpl com o parâmetro “title”.

{include file='header.tpl' title='Welcome!'}
{include file='footer.tpl'}

No header.tpl

<html>
<head>
<title>{$title|default:'Smarty World'}</title>
</head>
<body>

No footer.tpl

</body>
</html>

10. Formatando saídas numéricas

Você não precisa assinar várias variáveis com os mesmos valores em
diferentes formatos, porque o smarty possui um modificador de
variáveis que possibilita você formatar a saída de uma variável sem
modificar seu conteúdo. “string_format” usa a mesma formatting syntax
do sprintf() function do PHP.

Exemplo:

{$number}
{$number|string_format:'%.2f'}
{$number|string_format:'%d'}

Com o $number igual a 23.5787446, o código acima vai mostrar:

23.5787446
23.58
24

11. Manipulação de Datas

A regra da tumba é PHP coders sempre vão passar datas para o Smarty
como timestamps. Isso permite que os designers de template utilizar o
“date_format” modifier para o controle total sobre a formatação da
data. Você pode também facilmente compará-las se quiser.

date format Padrão:

{$createDate|date_format}

Saída:
Feb 28, 2009

date format Customizado:

{$createDate|date_format:'%Y/%m/%d'}

Mostra:
2009/02/28

Comparando datas:

{if $startDate < $endDate}
. . . faça alguma coisa . .
{/if}

Para converter a saída do {html_select_date} para o formato timestamp do PHP, use a função a seguir:

<?php
function makeTimeStamp($year='', $month='', $day='')
{
if(empty($year)) {
$year = strftime('%Y');
}
if(empty($month)) {
$month = strftime('%m');
}
if(empty($day)) {
$day = strftime('%d');
}

return mktime(0, 0, 0, $month, $day, $year);
}
?>

12. Obfuscando endereços de e-mail

Quando você exibe endereços de e-mail em suas páginas, tenha certeza
de que estes estão obfuscados para os spam bots não fazerem a festa com
eles. No Smarty, você pode usar a {mailto} tag para
obfuscar qualquer endereço de e-mail. Functiona de forma que você
incorpora o endereço de e-mail via javascript, logo, o mesmo não
aparece via código HTML se você exibir o código fonte.

Exemplo

<div id="contact">Entre em contato pelo e-mail:
{mailto address=$emailAddress encode='javascript' subject='Hi Smarty'}
</div>

13. Alternando estilos CSS

É comum possuirmos em nosso sistema tabelas, onde cada linha aparece
de cor diferente para facilitar a leitura e a localização da
informação. No Smarty, utilizando o {cycle} tag você consegue alternar por exemplo o fundo de suas células a cada siclo de um laço de repetição.

Aqui vai um código que alterna entre as classes css “odd” or “even”.

<table>
{section name=item loop=$items}
<tr class="{cycle values='odd,even'}">
<td>{$items[item].title}</td>
<td>{$items[item].description}</td>
</tr>
{/section}
</table>

14. Buscando e Apresentando Conteúdo On Demand

Tradicionalmente, adicionamos componentes PHP dentro do próprio
conteúdo para que esta tarefa seja possível, porém, isso requer um
pouco de lógica e de mais afinidade com o PHP. Por outro lado,
removendo componentes do seus templates requer um pouco de lógica de
programação para que você consiga otimizar suas rotinas em busca de um
melhor desempenho

Possívelmente a manutenção para estes tipos de templates pode ser um
verdadeiro pesadelo para projetos mais longos e mais complexos,
especialmente quando o programador PHP e o template designer são duas
pessoas diferentes.

A solução é escrever componentes (functions) que são executadas on demand (quando requisitadas) pelo template.

Existem dois caminhos para se escrever on demand scripts:

  • Use a tag {insert}

Funciona como se estivessemos chamando uma função pré definida pelo
programador. Essas funções começam sempre com “insert_” e insere o
retorno das funções dentro do template onde a tag {insert} é colocada. A tag é útil para exibir conteúdos dinâmicos porque o conteúdo nunca é cachgeado regularmente.

O código PHP:

<?php
require 'Smarty.class.php';
$smarty = new Smarty;
$smarty->display('index.tpl');

function insert_getNews($params)
{
if ($params['type'] == 'latest') {
// recebe as notícias e processa
}
// retorna o resultado
return $html;
}
?>

O template, chamado “index.tpl”:

<div class="news">
<h3>Latest Smarty News</h3>
{insert name='getNews' type='latest'}
</div>
  • Escreva componentes como plugins

Plugin é um modulo que existe dentro do Smarty que contém scripts
PHP para buscar e exibir dados necessários e assiná-los dentro de
variáveis de template. É sempre carregado on demand, sendo assim, você
não precisa se preocupar a respeito de adicionar ou remover linhas de
lógica dos seus scripts para otimizá-los.

Como exemplo, aqui vai um simples plugin para notícias:

function.news.php  observe o naming convention e
coloque o arquivo dentro do diretório de plugins, geralmente
“smarty/libs/plugins” de outra maneira set o $plugins_dir.

<?php
// function para receber as notícias
function fetch_news($symbol)
{
// o news items pode ser recebido pelo banco de dados
// mas para este exemplo, eu só criei um array para simular o retorno.
$items = array(
array('title'=>'Smarty News', 'description'=>'Great Smarty Templates'),
array('title'=>'PHP News', 'description'=>'Smarty Templating Engine'),
);
return $items;
}

function smarty_function_news($params, &$smarty)
{
// chamando nossa função personalizada
$news = fetch_news($params['symbol']);

// assinando como uma variavel de template
$smarty->assign($params['assign'], $news);
}

Para usar o plugin Smarty News no seu index.tpl:

{news symbol='SMARTY' assign='items'}
<ul>
{section name=item loop=$items}
<li><h3>{$items[item].title}</h3><p>{$items[item].description}</p></li>
{/section}
</ul>

15. Utilizando Códigos CSS e Javascript Dentro de Templates Smarty

Por padrão, Smarty divide tudo que esta dentro de { e } incluindo os utilizados pelas regras CSS e funções Javascript.

Existem quatro caminhos para escapar da divisão do Smarty:

1. Separe seus arquivos CSS e Javascript em
arquivos separados de forma que você possa incluí-los dentro do seu
template utilizando os métodos padrão do HTML.

Incluindo o estilo CSS:

<link rel="stylesheet" href="style.css" type="text/css />

Incluindo arquivos Javascript:

<script type="text/javascript" src="popup.js"></script>

2. Adicione a tag {literal} no início e no fim {/literal} de códigos CSS ou Javascript que estejam incorporados ao seu documento, assim, o Smarty vai deixar tudo o que estiver entre o {literal} e {/literal} em paz.

CSS Incorporado:

<style type="text/css">
<!--
{literal}
p {text-indent: 10pt}
body {margin:0; padding:0;}
{/literal}
-->
</style>

Javascript Incorporado:

<script language="javascript" type="text/javascript" >
<!--
{literal}
function hello_world(){
alert('Hello Smarty World');
}
{/literal}
-->
</script>

3. Mude o Smarty $left_delimiter e $right_delimiter
de forma que os delimitadores não se confundam com os delmitadores de
outras linguagens. Além disso, isso possibilita que você insira
variáveis de template dentro de arquivos CSS e Javascript dinâmicamente.

O Código PHP:

<?php
require 'Smarty.class.php';

$smarty = new Smarty;

$smarty->left_delimiter = '<!--{';
$smarty->right_delimiter = '}-->';

$smarty->assign('title', 'The Smarty Template Engine');
$smarty->assign('element', 'h1');
$smarty->assign('size', '36px');
$smarty->assign('popup', 'alert');
$smarty->display('index.tpl');
?>

O Smarty Template “index.tpl”:

<head>
<style type="text/css">
<!--
<!--{$element}--> {font-size: <!--{$size}-->}
-->
</head>
<body>
<<!--{$element}-->><!--{$title}--></<!--{$element}-->>
<script language="javascript" type="text/javascript" >
<!--
function show_popup()
{
<!--{$popup}-->('<!--{$title}-->');
}
//-->
</script>
</body>

O código acima vai mostrar:

<head>
<style type="text/css">
<!--
h1 {font-size: 36px}
-->
</head>
<body>
<h1>The Smarty Template Engine</h1>
<script language="javascript" type="text/javascript" >
<!--
function show_popup()
{
alert('The Smarty Template Engine');
}
//-->
</script>
</body>

4. Use {ldelim} e {rdelim} no lugar de { and } na definição das regras dos seus arquivos css e na hora de escrever funções javascript.

Exemplo, arquivos CSS:

<style type="text/css">
<!--
p {ldelim}text-indent: 10pt;{rdelim}
body {ldelim}margin:0; padding:0;{rdelim}
-->
</style>

Mostrará:

<style type="text/css">
<!--
p {text-indent: 10pt;}
body {margin:0; padding:0;}
-->
</style>

16. Caching Smarty Templates

Caching aumenta a velocidade em metodos do tipo display() e fetch()
salvando a saída destes metodos em arquivos separados. Vale lembrar
que o cache somente é utilizado se o conteúdo não mudou. Set $caching =
2 e utilize o $cache_lifetime para controlar quanto tempo o cache da informação deverá ser matido para depois então ser atualizado.

Ativando o cache:

<?php
require 'Smarty.class.php';
$smarty = new Smarty;

// Quando $caching = 1,
// $cache_lifetime = 1 força o cache para nunca expirar
// $cache_lifetime = 0 vai sempre regenerar o cache
// Quando $caching = 2,
// $cache_lifetime seta a vida do cache, mas o mesmo pode ser setado para templates individuais.
$smarty->caching = 2; // lifetime é para cada cache

// Regenera o conteúdo cacheado se nenhum template ou arquivo de configuração for parte do cache que estiver sendo modificado.
$smarty->compile_check = true;

// $smarty->force_compile = true; vai forçar o cache ser sempre regenerado

// assume o cache_lifetime para o template index.tpl para 5 minutos
$smarty->cache_lifetime = 300;
$smarty->display('index.tpl');

// assume o cache_lifetime para o template home.tpl para uma hora
$smarty->cache_lifetime = 3600;
$smarty->display('home.tpl');
?>

Duas coisas que devem ser consideradas quando implementamos caching:

  1. Não é recomendado colocar o diretório de cache
    abaixo da pasta raiz do servidor. Set $cache_dir para um diretório que
    não seja acessível via web.
  2. Tenha certeza de que o diretório do cache tem permissão de escrita no servidor.

Enfim, concluímos. 16 Técnicas Smarty Scripting para deixar seus
templates ainda mais inteligentes para o seus projetos Web Smarty.

Para qualquer outra coisa, visite o site oficial do Smarty Template Engine para o PHP.

Se você tem alguma outra dica que não foi incluída aqui, sinta-se à vontade para incluí-la nos comentários.

Este artigo é uma tradução/adaptação do artigo 16 Very Useful Smarty Scripting Tips and Techniques to Make Templates Smarter.