Neste primeiro post de 2010 dedico a atender um pedido feito em um comentário de post passado de mostrar como integrar o Smarty (funcionando tanto com o 2.6.26 quanto com o 3.0b5) nas versões mais novas do Zend Framework. A base usada para fazer ele foi da Documentação Oficial do Zend Framework, fiz poucas alterações na classe que eles criaram.

Em versões anteriores, era necessário explicitamente trocar o Zend_View pelo Smarty no index. Agora, temos a opção de criar uma classe que transforme outro sistema de templates em uma instância da Zend_View, e o melhor: de maneira simples e sem contar com eventuais gambiarras para ‘mascarar’ alguns problemas que dava quando substituíamos.

Optando pelo Smarty

Antes de começar a mexer com Smarty, temos que usar o Autoloader do Zend para poder rodar tudo sem precisar dar includes em todas as páginas, em especial o Bootstrap. Para isso, coloque dentro da sua index, antes de instanciar o Zend_Application:

require_once 'Zend/Loader/Autoloader.php';

$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('My_');

Esse código basicamente tornará todas as classes dentro da pasta library/My visíveis, usando o mesmo esquema de nomeação do Zend. Por exemplo, eu coloquei a classe de integração com o Smarty (que mostrarei mais abaixo) dentro de My/View/Smarty.php, e portanto, devo chamá-la de My_View_Smarty.

Ok, vamos lá: baixe o Smarty e descompacte-o dentro da pasta library.

Altere o Bootstrap, adicionando o método:

protected function _initView()
    {

        // aqui podemos passar quaisquer parâmetros que sejam atributos do objeto smarty
        // se quisermos habilitar o cache, por exemplo:
        $params = array(
                      'caching'        => true,
                      'cache_lifetime' => 60
                  );

        $view = new My_View_Smarty('../application/views/smarty/', $params);
        $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
        $viewRenderer->setView($view)
                     ->setViewBasePathSpec($view->getEngine()->template_dir)
                     ->setViewScriptPathSpec(':controller/:action.:suffix')
                     ->setViewScriptPathNoControllerSpec(':action.:suffix')
                     ->setViewSuffix('tpl');
        Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

    }

Crie o arquivo de implementação do Smarty:

<?php

require_once('Smarty/Smarty.class.php');

class My_View_Smarty implements Zend_View_Interface
{

    /**
     * Smarty object
     * @var Smarty
     */
    protected $_smarty;

    /**
     * Constructor
     *
     * @param string $tmplPath
     * @param array $extraParams
     * @return void
     */
    public function __construct($tmplPath = null, $extraParams = array())
    {
        $this->_smarty = new Smarty();

        if (null !== $tmplPath) {
            $this->setScriptPath($tmplPath);
        }

        foreach ($extraParams as $key => $value) {
            $this->_smarty->$key = $value;
        }
    }

    /**
     * Return the template engine object
     *
     * @return Smarty
     */
    public function getEngine()
    {
        return $this->_smarty;
    }

    /**
     * Set the path to the templates
     *
     * @param string $path The directory to set as the path.
     * @return void
     */
    public function setScriptPath($path)
    {

        if (is_readable($path)) {
            $this->_smarty->template_dir = $path."templates";
            $this->_smarty->compile_dir  = $path."templates_c";
            $this->_smarty->cache_dir    = $path."cache";
            $this->_smarty->config_dir   = $path."config";
            return;
        }

        throw new Exception('Invalid path provided');
    }

    /**
     * Retrieve the current template directory
     *
     * @return string
     */
    public function getScriptPaths()
    {
        return array($this->_smarty->template_dir);
    }

    /**
     * Alias for setScriptPath
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function setBasePath($path, $prefix = 'Zend_View')
    {
        return $this->setScriptPath($path);
    }

    /**
     * Alias for setScriptPath
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function addBasePath($path, $prefix = 'Zend_View')
    {
        return $this->setScriptPath($path);
    }

    /**
     * Assign a variable to the template
     *
     * @param string $key The variable name.
     * @param mixed $val The variable value.
     * @return void
     */
    public function __set($key, $val)
    {
        $this->_smarty->assign($key, $val);
    }

    /**
     * Allows testing with empty() and isset() to work
     *
     * @param string $key
     * @return boolean
     */
    public function __isset($key)
    {
        return (null !== $this->_smarty->get_template_vars($key));
    }

    /**
     * Allows unset() on object properties to work
     *
     * @param string $key
     * @return void
     */
    public function __unset($key)
    {
        $this->_smarty->clear_assign($key);
    }

    /**
     * Assign variables to the template
     *
     * Allows setting a specific key to the specified value, OR passing
     * an array of key => value pairs to set en masse.
     *
     * @see __set()
     * @param string|array $spec The assignment strategy to use (key or
     * array of key => value pairs)
     * @param mixed $value (Optional) If assigning a named variable,
     * use this as the value.
     * @return void
     */
    public function assign($spec, $value = null)
    {
        if (is_array($spec)) {
            $this->_smarty->assign($spec);
            return;
        }

        $this->_smarty->assign($spec, $value);
    }

    /**
     * Clear all assigned variables
     *
     * Clears all variables assigned to Zend_View either via
     * {@link assign()} or property overloading
     * ({@link __get()}/{@link __set()}).
     *
     * @return void
     */
    public function clearVars()
    {
        $this->_smarty->clear_all_assign();
    }

    /**
     * Processes a template and returns the output.
     *
     * @param string $name The template to process.
     * @return string The output.
     */
    public function render($name)
    {
        return $this->_smarty->fetch($name);
    }

}

Para funcionar, basta criar as pastas de templates, cache e configs usadas pelo Smarty.

Exemplo de execução

O controller não fica muito diferente do que já era com o Zend_View comum… usando o controller index por exemplo:

    public function indexAction()
    {
        // cria algumas variáveis
        $valor1 = mt_rand(0,100);
        $valor2 = array(
            array('id' => '1', 'titulo' => 'Teste 1'),
            array('id' => '2', 'titulo' => 'Teste 2'),
            array('id' => '3', 'titulo' => 'Teste 3')
        );
        // inclui as variáveis na view
        $this->view->assign('valor1', $valor1);
        $this->view->assign('valor2', $valor2);
    }

No arquivo views/smarty/index/index.tpl, teríamos:

<p>{$valor1}</p>
<table>
    <tr>
        <th>Código</th>
        <th>Título</th>
    </tr>
    {foreach from=$valor2 item=registro}
    <tr style="background-color: {cycle values="#ff0000,#00ff00"}">
        <td>{$registro.id}</td>
        <td>{$registro.titulo}</td>
    </tr>
    {/foreach}
</table>

Espero que tenham gostado do tutorial e que tenha facilitado a vida dos amantes de Smarty e ZF!

Posted in php at janeiro 2nd, 2010. 8 Comments.

Curioso depois da palestra Smarty 3 – O Céu é o Limite! na PHP Conf 2009, resolvi dar uma checada na versão desse sistema de templates que tanto gosto e costumo usar em meus projetos. Primeiro, vou falar um pouco sobre o que foi falado na palestra e que está no arquivo de apresentação, que foi disponibilizado aqui pelo autor. Depois, algumas observações e opiniões de algumas pesquisadas pela internet a fora e fuçadas.

Obs.: esse post foi feito para falar do Smarty 3 beta 5, ou seja, algumas mudanças e melhorias podem acontecer conforme o projeto ficar mais maduro.

Novidades

A maioria dessas novidades estão no slide, mas vou falar um pouco de cada:

Melhoria no sistema de plugins: só olhando para o esquema de diretórios do smarty, e podemos ver que está diferente: agora, tem uma pasta para plugins comuns, como já havia antes, e plugins do sistema. Nos plugins do sistema, podemos encontrar todo o código interno do smarty, incluindo métodos chamados no Smarty.class.php e funções internas do template como {foreach}.

Novo sistema de Cache: agora podemos especificar setar o caching como true e dizer que algumas partes não queremos que o cache seja usado, com a tag {nocache}. Chegaram até a perguntar durante a palestra se dava pra fazer o contrário, e setar apenas onde queremos que tenha cache, mas infelizmente não é possivel.

Templates como código PHP embutido: tem alguns templates em PHP puro e não quer reescrever para a linguagem smarty? Sem problemas, agora isso é possível, sem fazer nenhuma alteração se quer no template:

$smarty->display('php:template.php');

Por conta disso, a tag {php} agora foi desabilitada por padrão. Para compatibilidade com Smarty 2, ela pode ser habilitada com $smarty->allow_php_tag=true.

Total compatibilidade com Javascript, CSS, Jquery, etc.: atire a primeira pedra quem nunca ficou nervoso porque o parser do smarty dava erro quando encontrava as chaves de CSS e Javascript e precisava do {literal}{/literal} ou então mudar os delimitadores … no Smarty 3 não precisamos mais disso: agora ele só interpreta como tag própria se não tiver espaço depois e se tiver, é ignorado;

Código mais próximo da linguagem PHP: tags como {foreach} foram alteradas e usam a mesma sintaxe do PHP. Foram adicionados controles mais próximos do PHP também, como {else if}, {while} e {for}. Outro exemplo é que o {assign} não é mais necessário, já que podemos usar uma atribuição igual a que usamos no PHP. Por exemplo:

{$mensagem = "Data atual"}
{$data = $smarty.now|date_format:"%d/%m/%Y %H:%M:%S"}

{$mensagem = "$mensagem: $data"}

Inclusão de diretórios de templates: podemos agora definir diversas pastas para templates com as funções setTemplateDir() e addTemplateDir(). A primeira recebe um array de diretórios, enquanto a segunda recebe um valor único que pode ser tanto string quanto array e que é adicionado ao array de templates. Na hora de encontrar algum arquivo, ele é buscado do primeiro diretório encontrado ao último.

Funções dentro de templates: é possível agora definirmos funções em templates, para reuso de código. Um exemplo:

{function name=menu level=0}
  <ul class="level{$level}">
  {foreach $data as $entry}
    {if is_array($entry)}
      <li>{$entry@key}</li>
       {menu data=$entry level=$level+1}
    {else}
      <li>{$entry}</li>
    {/if}
  {/foreach}
  </ul>
{/function}

{$menu = ['item1','item2','item3' => ['item3-1','item3-2','item3-3' =>
  ['item3-3-1','item3-3-2']],'item4']}

{menu data=$menu}

Ou seja: {function} tem apenas o atributo name como obrigatório, e podemos ter vários adicionais; para chamar uma função, devemos usar uma tag com o mesmo nome da função (no exemplo, foi menu), e por isso deve ser usado apenas nomes não usados em tags do próprio smarty.

Herança de Templates: bem, esse não estava no slide, mas achei que é uma novidade interessante, que outros sistemas de templates já tinham. A herança de templates consiste em ter um template com blocos que pode ser alterado por outros templates filhos, assim como quando estendemos classes com o PHP normal. No Smarty 2 isso não era possível, mas essa necessidade era resolvida com o {include}.

O Smarty possibilita fazer isso de 2 maneiras. A primeira:

base.tpl:

<html>
<head>
  <title>{block name="title"}default{/block}</title>
  {block name="head"}{/block}
</head>
<body>
  {block name="body"}{/block}
</body>
</html>

page.tpl:

{extends file="base.tpl"}
{block name="title"} my title {/block}
{block name="head"} <!-- insert js/css here --> {/block}
{block name="body"} <!-- insert content here --> {/block}

content.tpl:

{extends file="page.tpl"}
{block name="body"} <h1>Some Content</h1> {/block}

Chamando o content.tpl no display() do smarty, temos como resultado:

<html>
<head>
  <title> my title </title>
   <!-- insert js/css here -->
</head>
<body>
   <h1>Some Content</h1>
</body>
</html>

Esclarecendo, temos 2 novas tags envolvidas: {extends} e {block}. O {extends} serve que nem o extends para classes php, você indica ao filho qual o template que ele herdará. Já o {block} é um pedaço de código no qual o conteúdo do template que está sendo gerado é sobreposto sempre que um filho tiver um conteúdo diferente. Analisando o resultado final isso fica evidente: sempre que o filho teve um {block} com o mesmo nome, o conteúdo foi trocado. Além disso, pudemos ver no content.tpl que não é necessário que todos os blocos sejam alterados.

Porém, como eu falei anteriormente, podemos fazer de outro jeito:

$smarty->display('extends:base.tpl|page.tpl|content.tpl');

Nesse caso, não precisaríamos usar o {extends} nos tpls, definindo dinâmicamente a herança dentro do próprio PHP.

Primeiras Impressões

Gostei de algumas facilidades que a nova versão proporciona, como não precisar mais do {literal}, a atualização do próprio sistema de templates, e a compatibilidade com a versão 2.

Mas nem tudo também me agradou. A grande expectativa minha para essa versão era justamente a melhora de performance. Ok, eu não criei benchmarks para poder provar com números, mas fiquei até preocupado quando li esse post do fórum do Smarty e alguns poucos comentários pela web a fora de que o Smarty 3 é mais lento ou pelo menos igual ao Smarty 2 nesse sentido. A esperança é que, como ainda é uma versão beta, isso ainda possa ser melhorado.

Outra coisa que eu esperava do smarty era que ele passasse a ficar mais parecido com uma linguagem de marcação, como me parece ser a tendência, ao invés de se aproximar cada vez mais do que já temos no PHP. Quero dizer, será que é realmente vantajoso tornar a compilação mais lenta com a interpretação do PHP no Smarty para continuar escrevendo códigos imperativos dentro da parte de visualização?

E por fim, temos a falta de documentação da nova versão no site. A única coisa que achei deles foi um txt que descreve algumas funcionalidades da versão beta.

Por enquanto é isso, está bom, mas acho que poderia ser melhor. Quando o Smarty 3 for lançado oficialmente e tiver uma documentação, espero ter algumas surpresas quanto as melhorias da nova versão. E você, o que achou do Smarty 3?

Posted in php at dezembro 18th, 2009. 3 Comments.

Continuando do post passado, agora vou tratar de assuntos mais específicos do Smarty: arquivos de configuração e algo sobre cache. Aqui usarei a mesma classe e index utilizados no post passado.

Arquivos de Configuração

São arquivos úteis normalmente para que o designer possa setar variáveis globais para os templates, como por exemplo o título da página ou as cores de fundo. No post passado, registrei a pasta ‘configs’ para isso.

Para começar, um exemplo bem simples:

# arquivo my.conf
pageTitle = "Teste Smarty"

[Test]
pageTitle = "Artigo Smarty"

[Production]
pageTitle = "Tutorial Smarty"

Temos aí grande parte das regras dos arquivos configuração:

  1. na primeira linha temos um comentário, que deve sempre ser feito com o #;
  2. na linha seguinte, temos o nome da nossa variável(pageTitle) e um valor para ela, que poderia estar tanto sem quanto com aspas ou mesmo com apóstrofos. Se tivesse mais de uma linha, o valor deveria ter 3 aspas como delimitador;
  3. e as chamadas seções, que são strings entre colchetes []. No meu exemplo, temos 2 seções, e suas variáveis são carregadas apenas quando chamamos a seção em específico. Tudo o que vem antes das seções faz parte das variáveis globais, que são sempre chamadas quando o arquivo de configuração é setado no smarty. Quando uma variável global possui o mesmo nome de uma variável de seção, o valor usado pelo smarty é sempre o da seção.

Para ver o funcionamento do arquivo de configuração, precisamos chamá-la pelo smarty. Podemos fazer isso de 2 maneiras:
ou no próprio php:

// com base na classe criada no primeiro passo, usamos o $this
// mas se não for o $this, será a variável que representa o objeto do smarty
// na função, colocamos o nome do arquivo e, opcionalmente, a seção
$this->config_load('my.conf', 'Test');

ou direto no tpl:

{config_load file="my.conf" section="Test"}

Feito isso, podemos chamar a variável no tpl com 2 sintaxes diferentes:

{#pageTitle#}
ou
{$smarty.config.pageTitle}

Executando de qualquer uma dessas maneiras, teremos como resultado Artigo Smarty no tpl, pois o valor da variável da seção substituiu o da variável global.
Bem, sobre arquivos de configuração é isso: dei um exemplo de arquivo que é normalmente usado em back-end, de configurações para diferentes níveis de uso (Teste e Produção), mas para o smarty é mais usado para diferenciar páginas (index, cadastro, login, etc).

Caching

Outra importante funcionalidade do Smarty é o seu sistema de caching: em geral, o cache é um local de armazenamento temporário na qual dados que são frequentemente acessados possam ser armazenados para rápido acesso. Uma vez que esse dado esteja em cache, ele pode ser acessado diretamente ao invés de refazer todo o processo que gerou os mesmos dados anteriormente.

O Smarty faz exatamente isso: quando habilitamos o cache e ele executa o display(), é criado um arquivo em puro html e pronto para ser retornado. Dessa maneira, conteúdos que não mudam constantemente podem ser recuperados rapidamente. Porém, como estamos lidando com php, e consequentemente teremos conteúdos dinâmicos (principalmente quanto a banco de dados), precisamos controlar o cache para conseguir tornar o conteúdo dinâmico e de rápido acesso.

Caching Simples

Para habilitar o cache no Smarty, vamos alterar a nossa classe usada no post anterior:

// lembrando que o $this se refere ao objeto da classe Smarty
$this->caching = true;

Dessa maneira, o nosso cache estará habilitado e o arquivo será gerado novamente a cada hora na pasta ‘cache’, conforme definimos no post passado. Podemos alterar o tempo de geração com outra variável do Smarty:

$this->cache_lifetime = 10;

Setamos portanto, 10 segundos para que a página seja gerada novamente. Claro que esse tempo depende de que conteúdo estamos lidando e qual a necessidade de tê-lo sempre atualizado.
Vamos então a um exemplo prático… no nosso php, vamos setar um valor randômico entre 0 e 100, que a cada execução geraria um número diferente:

$smarty->assign('random', mt_rand(0, 100));

Chamando a variável {$random} no Smarty, podemos observar que o valor randômico permanece o mesmo durante 10 segundos e depois se altera novamente. Mas tem um detalhe: o cache está funcionando, mas de qualquer forma, dentro do php, o nosso conteúdo dinâmico ainda está sendo executando, tornando o cache do Smarty ainda não muito eficiente. Para isso, o Smarty nos proporciona a função is_cached(), que poderíamos chamar na nossa index:

if( !$smarty->is_cached('index.tpl') ) {
    $smarty->assign('random', mt_rand(0, 100));
}

Dessa forma, podemos verificar se o arquivo tpl já está em cache ou não… se não estiver, então mandamos executar o conteúdo dinâmico, mas se já estiver ele só lerá o arquivo gravado em cache e exibirá ao usuário.

Cachings múltiplos

Pode acontecer de precisarmos ter mais de um arquivo de cache para cada página: imagine que temos um site artigos, e que temos vários usuários que podem cadastrar artigos. Se tivermos uma página que retorna todos os artigos do usuário, precisaremos de um arquivo de cache para cada usuário, uma vez que a mesma página poderá ter vários conteúdos diferentes.

Para tornarmos isso útil, usaremos o segundo parâmetro do display():

// para não fugir do tema, vamos considerar que só usuários logados acessam a página
// e vamos considerar que $_SESSION['id_usuario'] sempre retornará um valor válido
$id_usuario = $_SESSION['id_usuario'];
// verificamos se já existe o arquivo em cache para esse usuário
if( !$smarty->is_cached('arquivo.tpl', $id_usuario) ) {
    // como não existe, vamos ao banco em busca dos artigos
    $contents = get_database_contents($id_usuario);
    $smarty->assign('contents', $contents);
}
$smarty->display('arquivo.tpl', $id_usuario);

O que acontece é que se não existir conteúdo em cache, o php vai pegar os dados do banco e quando chegar no display(), o arquivo cache será criado para o usuário testado. Se já existir o cache, então o display apenas retornará o arquivo em cache.

Observação: é preciso ter cuidado com múltiplos caches! Use-o apenas quando realmente precisa ter vários tipos de conteúdos em uma mesma página, como no exemplo. Colocar IDs em caches significa gerar mais arquivos, e se não for corretamente usado, pode ocupar um espaço desnecessariamente grande no servidor. No exemplo passado, se for um site grande, podemos ter milhares de arquivos, mas em compensação, evitaríamos acessos desnecessários ao banco que poderiam prejudicar a visita dos usuários. Já no caso de um site que não terá um fluxo de visitas suficientemente grande, aplicar essa técnica não traria uma vantagem significativa.

Desistindo do cache

Para finalizar, se por acaso quisermos parar de usar o cache, basta setar:

$this->caching = false;

podemos limpar todos os arquivos do cache com:

$smarty->clear_all_cache();

ou então, para limpar individualmente:

$smarty->clear_cache('arquivo.tpl');

Concluindo

Chegamos ao fim de mais um artigo: vimos ao longo dele 2 funcionalidades que tornam o Smarty um excelente sistema de templates, facilitando e melhorando o nosso site. Talvez depois eu faça uma terceira parte sobre a criação de plugins no Smarty.

Posted in php at novembro 14th, 2009. No Comments.

Já demonstrei em tópicos anteriores que o Zend_View é um ótimo componente para facilitar a nossa camada view de um projeto MVC. Porém, ela não é a única: de fato, esse tipo de sistema é o que não falta para PHP, e o Smarty é uma das que se destaca.

O Smarty é uma biblioteca de template que facilita a aplicação do modelo MVC, que permite a separação do HTML e do PHP, facilitando o trabalho dos designers, que não precisam conhecer a linguagem para poder alterar o visual do site. Outras vantagens do Smarty:

  • É rápido: evita o overhead que muitos sistemas de template têm, pois compila apenas uma vez
  • É facilmente configurável: com pouco código podemos especificar onde estão as pastas necessárias para o funcionamento, as tags delimitadores (por padrão são “{}”), etc.
  • É extensível: podemos facilmente criar plugins, e portanto, podemos adequá-lo ao nosso projeto

Primeiros Passos

  1. Baixe a última versão estável do Smarty e extraia para uma pasta separada.
  2. Crie uma pasta separada para o nosso projeto, e detro dela crie uma pasta chamada Smarty
  3. Da pasta extraída, copie o que está dentro da pasta lib/ para a pasta Smarty do nosso projeto
  4. Na pasta do projeto, crie as pastas ‘templates’, ‘templates_c’, ‘configs’ e ‘cache’
  5. Crie um arquivo index.php, ainda sem nada
  6. Crie um arquivo index.tpl, também sem nada

Deve ficar assim:
Exemplo de projeto implementado com Smarty
Apenas lembrando: eu estou usando essa estrutura apenas para facilitar as chamadas, tanto que não é recomendável deixar essas pastas na raíz. Eu poderia ter chamado o Smarty de fora do projeto, ter outros nomes de pastas auxiliares e deixá-los em outros lugares também, mas deixei assim mesmo porque a minha intenção era apenas simplificar a explicação.

Entendendo

Temos a pasta ‘Smarty’, que possui todos os arquivos da biblioteca, e temos outras 4 pastas que são usadas pelo Smarty com diferentes objetivos:

  • cache: pasta usada pelo Smarty para armazenar os arquivos usados quando a opção de cache está habilitada
  • configs: pasta que deve conter os arquivos de configuração ‘.conf’
  • templates: pasta em que devem estar os arquivos ‘.tpl’, onde ficam os códigos html e do próprio smarty
  • templates_c: pasta usada pelo Smarty para armazenar as páginas compiladas

Lembrando que eu uso esses nomes porque são ‘padrões’ de quem usa o Smarty, mas podemos muito bem alterar os nomes na hora de configurá-lo.

Mãos à obra

Vamos então fazer um pouco de código: primeiro temos que chamar o Smarty e configurá-lo, e farei isso em uma classe isolada, apenas para não precisar fazer isso em todas as páginas que usaremos o Smarty:

<?php

require('Smarty/Smarty.class.php');

class Meu_Smarty extends Smarty {

    public function Meu_Smarty()
    {

        $this->Smarty();

        $this->template_dir    = 'templates';
        $this->compile_dir     = 'templates_c';
        $this->cache_dir       = 'cache';
        $this->config_dir      = 'configs';

        $this->left_delimiter  = '{{';
        $this->right_delimiter = '}}';

    }

}

Agora, a página index.php, que fazemos a chamada à classe e configuramos uma variável que chamaremos no tpl:

<?php

require('smarty.php');
$smarty = new Meu_Smarty();
// aqui dizemos que quermos uma variável chamada 'name' com o valor 'World'
$smarty->assign('name', 'World');
// especificamos o nome do tpl que será usado
$smarty->display('index.tpl');

?>

E finalmente o arquivo .tpl:

<html>
<head>
<title>Tutorial Smarty - Index
</head>
<body>

Hello {{$name}}!

</body>
</html>

Nada de muito trabalhoso: no index.php ‘dizemos’ ao Smarty para reconhecer uma variável chamada $nome, e no tpl chamamos-a.

Dificultando o nosso exemplo

Vamos a um processo mais difícil, mas também mais comum: queremos pegar dados de um banco de dados. Eu não vou entrar no mérito de conectar ao banco e tudo mais, mas normalmente quando fazemos isso, recebemos um array e usamos ele para mostrar os dados… então farei apenas isso, sem mudar o foco para o banco.

No index.php, teremos:

$resultado_banco = array(
    array(
        'id' => 1,
        'name' => 'Diego'
    ),
    array(
        'id' => 2,
        'name' => 'Tiago'
    ),
    array(
        'id' => 3,
        'name' => 'Paulo'
    )
);

$smarty->assign('resultado', $resultado_banco);

e no index.tpl:

<table>
    <tr>
        <th>ID</th>
        <th>Nome</th>
    </tr>
    {{section name="i" loop=$resultado}}
    <tr>
        <td>{{$resultado[i].id}}</td>
        <td>{{$resultado[i].name}}</td>
    </tr>
    {{/section}}
</table>

A grande diferença foi que usamos um comando pronto do Smarty, o {section}. Ele faz a função do loop no template, de forma que houve a iteração na variável $resultado, que era o array de resultados.
Uma coisa que precisa ser observada é a regra dos arrays no tpl, que no nosso exemplo foi o “{{$resultado[i].name}}”. A primeira vez que vi isso me perguntei “por que não {{$resultado[i]['name']}}, ou {{$resultado.i.name}}??”, mas bastou notar que ele trata índices numéricos com os conchetes e índices não numéricos com o ponto: aquele ‘i’ não é uma variável de fato, apenas um identificador de qual índice do array está sendo iterado no momento, enquanto que o ‘nome’ é o nome do índice que queremos pegar.

Conclusão

Acaba por aqui a primeira parte sobre o Smarty. Mostrei o básico, para quem não conhece, de como usar um ótimo sistema de templates para facilitar o uso das suas views, de maneira a desenvolver sem ficar aquele amontoado de código php junto do html.
Futuramente devo falar sobre coisas mais específicas do Smarty, como o uso do cache, arquivos de configuração e como criar plugins, recurso importantíssimo para estender o smarty com funcionalidades mais específicas.

Até a próxima!

Posted in php at novembro 1st, 2009. 4 Comments.