Modelos
A Nette utiliza o sistema de modelos Latte. O Latte é usado porque é o sistema de modelo mais seguro para PHP e, ao mesmo tempo, o sistema mais intuitivo. Você não precisa aprender muito de novo, você só precisa conhecer PHP e algumas tags de Latte.
É normal que a página seja completada a partir do modelo de layout + o modelo de ação. Isto é o que um modelo de layout
pode parecer, observe os blocos {block}
e a etiqueta {include}
:
<!DOCTYPE html>
<html>
<head>
<title>{block title}My App{/block}</title>
</head>
<body>
<header>...</header>
{include content}
<footer>...</footer>
</body>
</html>
E este poderia ser o modelo de ação:
{block title}Homepage{/block}
{block content}
<h1>Homepage</h1>
...
{/block}
Ele define o bloco content
, que é inserido no lugar de {include content}
no layout, e também
redefine o bloco title
, que sobrescreve {block title}
no layout. Tente imaginar o resultado.
Busca de modelos
O caminho para os modelos é deduzido de acordo com uma lógica simples. Ele tenta ver se um destes arquivos de gabaritos
existe em relação ao diretório onde se encontra a classe apresentadora, onde <Presenter>
é o nome do atual
apresentador e <view>
é o nome da ação atual:
templates/<Presenter>/<view>.latte
templates/<Presenter>.<view>.latte
Se o modelo não for encontrado, ele tentará procurar no diretório templates
um nível acima, ou seja, no mesmo
nível que o diretório com a classe apresentadora.
Se o modelo também não for encontrado lá, a resposta é um erro 404.
Você também pode mudar a visão usando $this->setView('otherView')
. Ou, em vez de procurar, especifique
diretamente o nome do arquivo modelo usando $this->template->setFile('/path/to/template.latte')
.
Você pode alterar os caminhos onde os modelos são pesquisados substituindo o método de formataçãoTemplateFiles, que retorna um conjunto de possíveis caminhos de arquivos.
O layout é esperado nos seguintes arquivos:
templates/<Presenter>/@<layout>.latte
templates/<Presenter>.@<layout>.latte
templates/@<layout>.latte
layout comum a vários apresentadores
<Presenter>
é o nome do atual apresentador e <layout>
é o nome do layout, que é, por
padrão, 'layout'
. O nome pode ser alterado com $this->setLayout('otherLayout')
, para que os
arquivos @otherLayout.latte
sejam experimentados.
Você também pode especificar diretamente o nome do arquivo do modelo de layout usando
$this->setLayout('/path/to/template.latte')
. O uso do $this->setLayout(false)
desabilitará a
busca do layout.
Você pode alterar os caminhos onde os modelos são pesquisados, substituindo o método formatLayoutTemplateFiles, que retorna uma série de possíveis caminhos de arquivos.
Variáveis no modelo
As variáveis são passadas para o modelo, escrevendo-as para $this->template
e depois estão disponíveis no
modelo como variáveis locais:
$this->template->article = $this->articles->getById($id);
Desta forma, podemos facilmente passar qualquer variável para os modelos. Entretanto, ao desenvolver aplicações robustas, muitas vezes é mais útil nos limitarmos. Por exemplo, ao definir explicitamente uma lista de variáveis que o modelo espera e seus tipos. Isto permitirá que o PHP verifique a digitação, que a IDE se autocomplete corretamente, e que a análise estática detecte erros.
E como definimos tal enumeração? Simplesmente sob a forma de uma classe e suas propriedades. Damos o mesmo nome ao
apresentador, mas com Template
no final:
/**
* @property-read ArticleTemplate $template
*/
class ArticlePresenter extends Nette\Application\UI\Presenter
{
}
class ArticleTemplate extends Nette\Bridges\ApplicationLatte\Template
{
public Model\Article $article;
public Nette\Security\User $user;
// e outras variáveis
}
O objeto $this->template
do apresentador será agora uma instância da classe ArticleTemplate
.
Portanto, o PHP verificará os tipos declarados quando eles forem escritos. E a partir do PHP 8.2 ele também alertará sobre a
escrita de uma variável inexistente, nas versões anteriores o mesmo pode ser alcançado usando o traço Nette\SmartObject.
A anotação @property-read
é para IDE e análise estática, fará com que o auto-completar funcione, veja PhpStorm e preenchimento de código por
$this->template.

Você também pode se dar ao luxo de sussurrar nos modelos, basta instalar o plugin Latte no PhpStorm e especificar o nome da classe no início do modelo, veja o artigo Latte: como digitar sistema:
{templateType App\Presenters\ArticleTemplate}
...
Também é assim que os modelos funcionam nos componentes, basta seguir a convenção de nomenclatura e criar uma classe de
modelos FifteenTemplate
para o componente, por exemplo FifteenControl
.
Se você precisar criar um $template
como instância de outra classe, use o método
createTemplate()
:
public function renderDefault(): void
{
$template = $this->createTemplate(SpecialTemplate::class);
$template->foo = 123;
// ...
$this->sendTemplate($template);
}
Variáveis padrão
Apresentadores e componentes passam várias variáveis úteis para os modelos automaticamente:
$basePath
é um caminho absoluto de URL para o dir raiz (por exemplo/CD-collection
)$baseUrl
é um URL absoluto para o dir raiz (por exemplohttp://localhost/CD-collection
)$user
é um objeto que representa o usuário$presenter
é o atual apresentador$control
é o atual componente ou apresentador$flashes
lista de mensagens enviadas por métodoflashMessage()
Se você usar uma classe de modelo personalizada, estas variáveis são passadas se você criar uma propriedade para elas.
Criação de links
No modelo, criamos links para outros apresentadores e ações da seguinte forma:
<a n:href="Product:show">detail</a>
O atributo n:href
é muito útil para tags HTML <a>
. Se quisermos imprimir o link em outro
lugar, por exemplo, no texto, usamos {link}
:
URL is: {link Home:default}
Para mais informações, consulte Criação de links.
Filtros personalizados, Etiquetas, etc.
O sistema de modelos Latte pode ser ampliado com filtros personalizados, funções, tags, etc. Isto pode ser feito diretamente
no render<View>
ou beforeRender()
método:
public function beforeRender(): void
{
// adicionando um filtro
$this->template->addFilter('foo', /* ... */);
// ou configurar diretamente o objeto Latte\Engine
$latte = $this->template->getLatte();
$latte->addFilterLoader(/* ... */);
}
A versão 3 do Latte oferece uma maneira mais avançada, criando uma extensão para cada projeto web. Aqui está um exemplo rudimentar de tal classe:
namespace App\Templating;
final class LatteExtension extends Latte\Extension
{
public function __construct(
private App\Model\Facade $facade,
private Nette\Security\User $user,
// ...
) {
}
public function getFilters(): array
{
return [
'timeAgoInWords' => $this->filterTimeAgoInWords(...),
'money' => $this->filterMoney(...),
// ...
];
}
public function getFunctions(): array
{
return [
'canEditArticle' =>
fn($article) => $this->facade->canEditArticle($article, $this->user->getId()),
// ...
];
}
// ...
}
Registramos usando a configuração#Latte:
latte:
extensions:
- App\Templating\LatteExtension
Traduzindo
Se você estiver programando uma aplicação multilíngüe, provavelmente precisará produzir parte do texto no modelo em
diferentes idiomas. Para fazer isto, o Nette Framework define uma interface de tradução Nette\Localization\Translator, que tem um
único método translate()
. Isto aceita a mensagem $message
, que geralmente é uma string, e quaisquer
outros parâmetros. A tarefa é devolver a string traduzida. Não há uma implementação padrão em Nette, você pode escolher
de acordo com suas necessidades entre várias soluções prontas que podem ser encontradas na Componette. Sua documentação lhe diz como configurar o tradutor.
Os modelos podem ser criados com um tradutor, que teremos passado para
nós, usando o método setTranslator()
:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator);
}
Alternativamente, o tradutor pode ser definido usando a configuração:
latte:
extensions:
- Latte\Essential\TranslatorExtension
O tradutor pode então ser usado, por exemplo, como um filtro |translate
, com parâmetros adicionais passados
para o método translate()
(ver foo, bar
):
<a href="basket">{='Basket'|translate}</a>
<span>{$item|translate}</span>
<span>{$item|translate, foo, bar}</span>
Ou como uma etiqueta de sublinhado:
<a href="basket">{_'Basket'}</a>
<span>{_$item}</span>
<span>{_$item, foo, bar}</span>
Para a tradução da seção de modelos, há uma etiqueta emparelhada {translate}
(desde Latte 2.11, anteriormente
foi usada a etiqueta {_}
):
<a href="order">{translate}Order{/translate}</a>
<a href="order">{translate foo, bar}Order{/translate}</a>
O tradutor é chamado por padrão em tempo de execução ao renderizar o modelo. Latte versão 3, no entanto, pode traduzir todo o texto estático durante a compilação do modelo. Isto economiza desempenho porque cada string é traduzida apenas uma vez e a tradução resultante é escrita na forma compilada. Isto cria múltiplas versões compiladas do modelo no diretório do cache, uma para cada idioma. Para fazer isto, basta especificar o idioma como segundo parâmetro:
protected function beforeRender(): void
{
// ...
$this->template->setTranslator($translator, $lang);
}
Por texto estático entendemos, por exemplo, {_'hello'}
ou {translate}hello{/translate}
. Textos não
estáticos, como {_$foo}
, continuarão a ser compilados em tempo real.