Por dentro de um Template Engine
Posted by Mathias Grimm on dezembro 25, 2008 in PHP
Bem vindo mais uma vez!
Nesse artigo pretendo mostrar mais ou menos o funcionamento de um template engine (em php).
Templates Engine são utilizados para separar a camada de apresentação das demais camadas. A separação da camada de visualização permite
um web designer dar manutenção nos códigos sem a necessidade de entender de programação.
Entre outras vantagens dos templates engine está a capacidade de se fazer cache das páginas.
Alguns php template engines existentes são: Smarty, Integrated Template, PHPTAL, Savant, Sigma, TinyButStrong e vlibTemplate
Bom, na verdade os único que utilizei foi o smarty, os demais foram retirados do livro PHP PROFISSIONAL.
Desenvolvi então um template engine didático =) apenas para terem idéia do que se passa por dentro de um template engine.
Basicamente o que acontece é uma substituição de variaveis.
Meu template engine só faz 2 coisas, registra variáveis e controla labels de internacionalização.
Vou chamar meu template engine de TE de agora em diante, para facilitar. o TE tem apenas uma classe TemplateEngine.
Teremos 1 página, com labels em 2 idiomas pt_BR e en_US. Para isso teremos um arquivo chamado teste.php que será o controlador.Nela instanciaremos a classe
TemplateEngine e definiremos as variaveis.Teremos o arquivo do template e os 2 arquivos de internacionalização
Segue Abaixo o código do controlador:
<?php include_once 'TemplateEngine.php'; //pt_BR $obTE = new TemplateEngine(TemplateEngine::pt_BR); $obTE->assign('name' ,'Mathias Grimm'); $obTE->assign('site' ,'http://mathiasgrimm.com.br'); $obTE->assign('comment' ,'Hello World!'); //en_US $obTE = new TemplateEngine(TemplateEngine::en_US); $obTE->assign('name' ,'Mathias Grimm'); $obTE->assign('site' ,'http://mathiasgrimm.com.br'); $obTE->assign('comment' ,'Hello World!'); ?>
Agora vou tentar explicar um pouco.
Linha 2:Temos o include do TE,após isso,na linha 5 instanciamos o TE, que recebe como argumento o idioma que será utilizado.
Nesse caso o código escrito está primeiramente em pt_BR e em seguida em en_US, justamente para demonstrar a funcionalidade da internacionalização.
Os idiomas disponíveis estão definidos como constantes da classe TemplateEngine.
Linha 6:Estamos criando uma variavel 'nome', que estará disponível no template
Linha 9:É onde falamos ao TE para compilar o template (na verdade,no TE, essa compilacao acontece em tempo de execução). index é o nome do template
que será buscado pelo compilador.
Agora mostrarei o template (HTML) e explicarei logo abaixo:
{config}index{/config} {#name}: {$name} {#site}: {$site} {#comment}: {$comment}
Linha 1: Entre as tags {config} e {/config} temos definido quem é arquivo de internacionalizacao dos labels
Linha 3: Temos a tag {#name} que será buscada no arquivo de internacionalização do idioma que está definido no momento.
Linha 3: temos a tag {$name} que conterá o valor que foi definido na linha 6 do controlador
Agora os arquivos de internacionalização:
pt_BR :
name = Nome site = Site comment = Comentário
en_US:
name = Name site = Site comment = Comment
Os arquivos de internacionalização são arquivos .ini .
O que está ao lado esquerdo do operador "=" é o nome do label, disponível no template como {#name} e o valor
a direita é o valor que será utilizado na compilação do template, assim como foi definido na linha 3 do template.
Segue agora o código do TE:
<?php class TemplateEngine { const pt_BR = 'pt_BR'; const en_US = 'en_US'; function __construct($lang) { $this->lang = $lang; } private $lang; function fetch($path) { $this->fetchVars($content); $this->fetchLabels($content); return $content; } function assign($name,$var) { $this->arVars[$name]=$var; } function fetchVars(&$content) { $pattern = '/\{\$.{1,}\}/'; foreach($arVars[0] as $var) { $newVal = $this->arVars[$curVal]; } } function fetchLabels(&$content) { $pattern = '/\{config\}.{1,}\{\/config\}/'; foreach($arVars as $var) { $path = "lang/{$this->lang}/".$curVal.".cfgte"; $pattern = '/\{\#.{1,}\}/'; foreach($internalArVars[0] as $var) { $newVal = $arLabels[$curVal]; } } } } ?>
Linha 4 e 5 : Definição das constantes de internacionalização. O valor definido para essas constantes será utilizado como o caminho da pasta
de internacionalização atual
Linha 7 a 10: O construtor recebe o valor do idioma, definido nas linhas 5 e 12 do controlador
Linha 15: Onde tudo começa. Esse método é responsável por compilar o template
Após a linha 15 temos a chamada aos métodos de compilacao de variaveis e labels. Caso eu realmente fosse fazer um template engine, seria ai onde colocaria
novas funcionalidades.
Linha 26: Método assign, ele é que registra uma variável, e armazena o valor dela dentro do array arVars, definido na linha 12.
Linha 31: Método que realiza a compilação (substituição de tags por variáveis). Ele tenta encontrar tags no formato {$}, ou seja, encontra as tags
{$name},{$site} e {$comment} que foram definidas no template e substitui pelos valores registrados dentro do controlador.
Como esse artigo é apenas didático (apesar de não ser uma didática muito boa =) ), utilizei uma maneira de substituir as váriaveis de forma que ficasse tudo ok,
sem me preocupar com desempenho. Utilizei uma combinação de expressão regular com str_replace.
Linha 44: Método responsável pela substiuição dos labels, registrados nos arquivos de internacionalização.
Linha 46: Pesquiso pela tag {config}{/config} para pegar o nome do arquivo de internacionalização que foi definido na linha 1 do template.
Linha 56: Defino o caminho do arquivo de internacionalização no formato lang/idioma/nome do arquivo de internacionalização,que no caso é index.
Por convenção o arquivo de internacionalização deve ter extensão .cfgte .
Linha 59: Parse do arquivo ini.
Linha 61: Dessa linha em diante ocorre a substituição de tags {#} assim como no método de substituição de variaveis, nesse caso serão encontradas
as tags {#name},{#site} e {#comment} que serão substituidas pelos valores registrados dentro dos arquivos de internacionalização.
Dessa forma o TE substitui as variaveis e labels e retorna o conteudo do arquivo de template para o controlador.
O resultado produzido pela execução do controlador será:
Nome: Mathias Grimm
Site: http://mathiasgrimm.com.br
Comentário: Hello World!
Name: Mathias Grimm
Site: http://mathiasgrimm.com.br
Comment: Hello World!
Dessa maneira temos um template engine funcionando...
Um verdadeiro template engine permite muitas outras funcionalidades disponíveis dentro do template. Mas a idéia é essa.
Substituição de código (tags) por valores .
Fica muito mais simples qualquer um dar manutenção no código do template, sem aquele código macarrão php e html.
Dessa forma poderia ser implemento um template engine para outras linguagens também, e utilizar o mesmo template fazendo uma abstração total da camada
de visualização.
Obrigado a todos,voltem sempre!
Para baixar os arquivos utilizados nesse artigo clique AQUI
Subscribe
Follow comments by subscribing to the Por dentro de um Template Engine Comments RSS feed.