Nette Documentation Preview

syntax
Página inicial do Blog
**********************

.[perex]
Vamos criar a home page exibindo seus posts recentes.


Antes de começarmos, você deve saber pelo menos algumas noções básicas sobre o padrão de design Model-View-Presenter (similar ao MVC((Model-View-Controller))):

- **Modelo*** - camada de manipulação de dados. Está completamente separado do resto da aplicação. Ele só se comunica com os apresentadores.

- **Veja** - uma camada de definição front-end. Ela torna os dados solicitados ao usuário usando modelos.

- **Presente** (ou Controlador) - uma camada de conexão. O apresentador conecta Modelo e Vista. Trata os pedidos, pede dados ao Modelo e depois os passa para a Vista atual.


No caso de uma aplicação muito simples como nosso blog, a camada Model consistirá apenas em consultas ao próprio banco de dados - não precisamos de nenhum código PHP extra para isso. Precisamos apenas criar camadas de Apresentador e Visualização. Na Nette, cada Apresentador tem suas próprias Views, portanto continuaremos com ambas simultaneamente.


Criação do banco de dados com Adminer .[#toc-creating-the-database-with-adminer]
================================================================================

Para armazenar os dados, utilizaremos o banco de dados MySQL porque é a escolha mais comum entre os desenvolvedores web. Mas se você não gostar, sinta-se à vontade para usar um banco de dados de sua escolha.

Vamos preparar o banco de dados que irá armazenar nossos posts no blog. Podemos começar de forma muito simples - apenas com uma única tabela para postagens.

Para criar o banco de dados, podemos baixar o [Adminer |https://www.adminer.org], ou você pode usar outra ferramenta para o gerenciamento do banco de dados.


Vamos abrir o Adminer e criar um novo banco de dados chamado `quickstart`.

Crie uma nova tabela chamada `posts` e adicione estas colunas:
- `id` int, clique em autoincrement (AI)
- `title` varchar, comprimento 255
- `content` texto
- `created_at` timestamp

Deveria ser assim:

[* adminer-posts.webp *]

```sql
CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;
```

.[caution]
É muito importante utilizar o **InnoDB** armazenamento de mesa. Você verá o motivo mais tarde. Por enquanto, basta escolher isso e enviar. Você pode clicar em Salvar agora.

Tente adicionar alguns exemplos de posts no blog antes de implementarmos a capacidade de adicionar novos posts diretamente de nossa aplicação.

```sql
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);
```


Conexão com o banco de dados .[#toc-connecting-to-the-database]
===============================================================

Agora, quando o banco de dados é criado e temos alguns posts nele, é o momento certo para exibi-los em nossa nova página brilhante.

Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em `config/common.neon`. Defina a conexão DSN((Data Source Name)) e suas credenciais. Deve ter este aspecto:

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*
```

.[note]
Esteja atento à indentação durante a edição deste arquivo. [O formato NEON |neon:format] aceita ambos os espaços e abas, mas não ambos juntos! O arquivo de configuração no Projeto Web utiliza abas como padrão.


Injetando a conexão do banco de dados .[#toc-injecting-the-database-connection]
===============================================================================

O apresentador `HomePresenter`, que listará os artigos, precisa de uma conexão de banco de dados. Para recebê-la, escreva um construtor como este:

```php .{file:app/Presenters/HomePresenter.php}
<?php
namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}
```


Carregamento de postes a partir do banco de dados .[#toc-loading-posts-from-the-database]
=========================================================================================

Agora vamos buscar os posts no banco de dados e passá-los para o template, que então renderizará o código HTML. É para isso que serve o chamado método *render*:

```php .{file:app/Presenters/HomePresenter.php}
public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}
```

O apresentador agora tem um método de renderização `renderDefault()` que passa dados para uma visualização chamada `default`. Os modelos do apresentador podem ser encontrados em `app/Presenters/templates/{PresenterName}/{viewName}.latte`, então neste caso o modelo será localizado em `app/Presenters/templates/Home/default.latte`. No modelo, uma variável chamada `$posts` está agora disponível, que contém os posts do banco de dados.


Modelo .[#toc-template]
=======================

Há um modelo genérico para toda a página (chamado *layout*, com cabeçalho, folhas de estilo, rodapé, ...) e depois modelos específicos para cada visualização (por exemplo, para exibir a lista de posts do blog), que podem substituir algumas das peças do modelo de layout.

Por padrão, o modelo de layout está localizado em `templates/@layout.latte`, que contém:

```latte .{file:app/Presenters/templates/@layout.latte}
...
{include content}
...
```

`{include content}` insere um bloco chamado `content` no modelo principal. Você pode defini-lo nos gabaritos de cada vista. Neste caso, editaremos o arquivo `Home/default.latte` desta forma:

```latte .{file:app/Presenters/templates/Home/default.latte}
{block content}
	Hello World
{/block}
```

Ele define o [bloco |latte:tags#block]*content*, que será inserido no layout. Se você atualizar o navegador, verá uma página com o texto "Hello world" (em código fonte também com cabeçalho e rodapé de página HTML definidos em `@layout.latte`).

Vamos exibir os posts do blog - editaremos o modelo desta forma:

```latte .{file:app/Presenters/templates/Home/default.latte}
{block content}
	<h1>My blog</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'j. n. Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}
```

Se você atualizar seu navegador, você verá a lista de seus posts no blog. A lista não é muito chique ou colorida, portanto, sinta-se à vontade para adicionar algum [CSS brilhante |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` e vinculá-lo em um layout:

```latte .{file:app/Presenters/templates/@layout.latte}
	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
```

A tag `{foreach}` itera todos os posts passados para a variável `$posts` e exibe um pedaço de código HTML para cada post. Assim como um código PHP faria.

A coisa `|date` é chamada de filtro. Os filtros são usados para formatar a saída. Este filtro particular converte uma data (por exemplo, `2013-04-12`) para sua forma mais legível (`12. 4. 2013`). O filtro `|truncate` truncata a string no comprimento máximo especificado, e adiciona uma elipse à extremidade se a string for truncada. Como isto é uma prévia, não há sentido em exibir o conteúdo completo do artigo. Outros filtros padrão [podem ser encontrados na documentação |latte:filters] ou você pode criar o seu próprio, se necessário.

Mais uma coisa. Podemos tornar o código um pouco mais curto e, portanto, mais simples. Podemos substituir as *etiquetas* por *n:atributos* desta forma:

```latte .{file:app/Presenters/templates/Home/default.latte}
{block content}
	<h1>My blog</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content}</div>
	</div>
{/block}
```

O `n:foreach`, simplesmente envolve o *div* com um *para cada* bloco (ele faz exatamente a mesma coisa que o bloco de código anterior).


Sumário .[#toc-summary]
=======================

Temos um banco de dados MySQL muito simples, com alguns posts em blogs. O aplicativo se conecta ao banco de dados e exibe uma lista simples dos posts.

{{priority: -1}}
{{sitename: Nette Quickstart}}

Página inicial do Blog

Vamos criar a home page exibindo seus posts recentes.

Antes de começarmos, você deve saber pelo menos algumas noções básicas sobre o padrão de design Model-View-Presenter (similar ao MVC):

  • **Modelo*** – camada de manipulação de dados. Está completamente separado do resto da aplicação. Ele só se comunica com os apresentadores.
  • Veja – uma camada de definição front-end. Ela torna os dados solicitados ao usuário usando modelos.
  • Presente (ou Controlador) – uma camada de conexão. O apresentador conecta Modelo e Vista. Trata os pedidos, pede dados ao Modelo e depois os passa para a Vista atual.

No caso de uma aplicação muito simples como nosso blog, a camada Model consistirá apenas em consultas ao próprio banco de dados – não precisamos de nenhum código PHP extra para isso. Precisamos apenas criar camadas de Apresentador e Visualização. Na Nette, cada Apresentador tem suas próprias Views, portanto continuaremos com ambas simultaneamente.

Criação do banco de dados com Adminer

Para armazenar os dados, utilizaremos o banco de dados MySQL porque é a escolha mais comum entre os desenvolvedores web. Mas se você não gostar, sinta-se à vontade para usar um banco de dados de sua escolha.

Vamos preparar o banco de dados que irá armazenar nossos posts no blog. Podemos começar de forma muito simples – apenas com uma única tabela para postagens.

Para criar o banco de dados, podemos baixar o Adminer, ou você pode usar outra ferramenta para o gerenciamento do banco de dados.

Vamos abrir o Adminer e criar um novo banco de dados chamado quickstart.

Crie uma nova tabela chamada posts e adicione estas colunas:

  • id int, clique em autoincrement (AI)
  • title varchar, comprimento 255
  • content texto
  • created_at timestamp

Deveria ser assim:

CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;

É muito importante utilizar o InnoDB armazenamento de mesa. Você verá o motivo mais tarde. Por enquanto, basta escolher isso e enviar. Você pode clicar em Salvar agora.

Tente adicionar alguns exemplos de posts no blog antes de implementarmos a capacidade de adicionar novos posts diretamente de nossa aplicação.

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);

Conexão com o banco de dados

Agora, quando o banco de dados é criado e temos alguns posts nele, é o momento certo para exibi-los em nossa nova página brilhante.

Em primeiro lugar, precisamos informar nossa aplicação sobre qual banco de dados utilizar. A configuração da conexão do banco de dados é armazenada em config/common.neon. Defina a conexão DSN e suas credenciais. Deve ter este aspecto:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*

Esteja atento à indentação durante a edição deste arquivo. O formato NEON aceita ambos os espaços e abas, mas não ambos juntos! O arquivo de configuração no Projeto Web utiliza abas como padrão.

Injetando a conexão do banco de dados

O apresentador HomePresenter, que listará os artigos, precisa de uma conexão de banco de dados. Para recebê-la, escreva um construtor como este:

<?php
namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}

Carregamento de postes a partir do banco de dados

Agora vamos buscar os posts no banco de dados e passá-los para o template, que então renderizará o código HTML. É para isso que serve o chamado método render:

public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}

O apresentador agora tem um método de renderização renderDefault() que passa dados para uma visualização chamada default. Os modelos do apresentador podem ser encontrados em app/Presenters/templates/{PresenterName}/{viewName}.latte, então neste caso o modelo será localizado em app/Presenters/templates/Home/default.latte. No modelo, uma variável chamada $posts está agora disponível, que contém os posts do banco de dados.

Modelo

Há um modelo genérico para toda a página (chamado layout, com cabeçalho, folhas de estilo, rodapé, …) e depois modelos específicos para cada visualização (por exemplo, para exibir a lista de posts do blog), que podem substituir algumas das peças do modelo de layout.

Por padrão, o modelo de layout está localizado em templates/@layout.latte, que contém:

...
{include content}
...

{include content} insere um bloco chamado content no modelo principal. Você pode defini-lo nos gabaritos de cada vista. Neste caso, editaremos o arquivo Home/default.latte desta forma:

{block content}
	Hello World
{/block}

Ele define o blococontent, que será inserido no layout. Se você atualizar o navegador, verá uma página com o texto „Hello world“ (em código fonte também com cabeçalho e rodapé de página HTML definidos em @layout.latte).

Vamos exibir os posts do blog – editaremos o modelo desta forma:

{block content}
	<h1>My blog</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'j. n. Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}

Se você atualizar seu navegador, você verá a lista de seus posts no blog. A lista não é muito chique ou colorida, portanto, sinta-se à vontade para adicionar algum CSS brilhante a www/css/style.css e vinculá-lo em um layout:

	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...

A tag {foreach} itera todos os posts passados para a variável $posts e exibe um pedaço de código HTML para cada post. Assim como um código PHP faria.

A coisa |date é chamada de filtro. Os filtros são usados para formatar a saída. Este filtro particular converte uma data (por exemplo, 2013-04-12) para sua forma mais legível (12. 4. 2013). O filtro |truncate truncata a string no comprimento máximo especificado, e adiciona uma elipse à extremidade se a string for truncada. Como isto é uma prévia, não há sentido em exibir o conteúdo completo do artigo. Outros filtros padrão podem ser encontrados na documentação ou você pode criar o seu próprio, se necessário.

Mais uma coisa. Podemos tornar o código um pouco mais curto e, portanto, mais simples. Podemos substituir as etiquetas por n:atributos desta forma:

{block content}
	<h1>My blog</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content}</div>
	</div>
{/block}

O n:foreach, simplesmente envolve o div com um para cada bloco (ele faz exatamente a mesma coisa que o bloco de código anterior).

Sumário

Temos um banco de dados MySQL muito simples, com alguns posts em blogs. O aplicativo se conecta ao banco de dados e exibe uma lista simples dos posts.