Nette Documentation Preview

syntax
Criação e Edição de Posts
*************************

Que grande momento. Temos um novo blog super legal, as pessoas estão discutindo nos comentários e finalmente temos algum tempo para mais programação. Embora gostemos de Adminer, não é tão confortável escrever nele posts de blogs. Talvez seja o momento certo para adicionar um formulário simples para adicionar novos posts diretamente de nosso aplicativo. Vamos fazer isso.

Vamos começar projetando a IU:

1. Na página inicial, vamos adicionar um link "Escrever novo post".
2. Ele mostrará um formulário com título e área de texto para o conteúdo.
3. Quando você clicar no botão Salvar, ele salvará o post do blog.

Mais tarde também adicionaremos autenticação e permitiremos apenas usuários logados para adicionar novos posts. Mas vamos fazer isso mais tarde. Que código precisaremos escrever para que funcione?

1. Criar um novo apresentador com um formulário para adicionar postos.
2. Definir uma chamada de retorno que será acionada após o envio bem sucedido do formulário e que salvará o novo post no banco de dados.
3. Criar um novo modelo para o formulário.
4. Adicionar um link para o formulário ao modelo da página principal.


Novo apresentador .[#toc-new-presenter]
=======================================

Nomeie o novo apresentador `EditPresenter` e salve-o em `app/Presenters/EditPresenter.php`. Ele também precisa se conectar ao banco de dados, então aqui novamente escrevemos um construtor que exigirá uma conexão com o banco de dados:

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

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

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


Formulário para salvar postes .[#toc-form-for-saving-posts]
===========================================================

Formulários e componentes já foram cobertos quando estávamos adicionando apoio para comentários. Se você estiver confuso sobre o tópico, vá verificar [como os formulários e componentes funcionam |comments#form-for-commenting] novamente, nós esperaremos aqui ;)

Agora adicione este método ao `EditPresenter`:

```php .{file:app/Presenters/EditPresenter.php}
protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Title:')
		->setRequired();
	$form->addTextArea('content', 'Content:')
		->setRequired();

	$form->addSubmit('send', 'Save and publish');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}
```


Salvando novos postos do formulário .[#toc-saving-new-post-from-form]
=====================================================================

Continue adicionando um método de manipulador.

```php .{file:app/Presenters/EditPresenter.php}
private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Apenas uma explicação rápida: ele pega os valores do formulário, insere-os no banco de dados, cria uma mensagem para o usuário de que o post foi salvo com sucesso e redireciona para a página onde esse post é publicado para que você possa ver como ele se parece.


Página para criar um novo posto .[#toc-page-for-creating-a-new-post]
====================================================================

Vamos apenas criar o modelo `Edit/create.latte`:

```latte .{file:app/Presenters/templates/Edit/create.latte}
{block content}
<h1>New post</h1>

{control postForm}
```

Tudo já deve estar claro a esta altura. A última linha mostra a forma que estamos prestes a criar.

Poderíamos também criar um método `renderCreate` correspondente, mas não é necessário. Não precisamos obter nenhum dado do banco de dados e passá-lo para o modelo, para que esse método fique vazio. Nesses casos, o método pode não existir em absoluto.


Link para a criação de postos .[#toc-link-for-creating-posts]
=============================================================

Você provavelmente já sabe como adicionar um link para `EditPresenter` e sua ação `create`. Experimente-o.

Basta adicionar ao arquivo `app/Presenters/templates/Home/default.latte`:

```latte
<a n:href="Edit:create">Write new post</a>
```


Postos de edição .[#toc-editing-posts]
======================================

Vamos também acrescentar a capacidade de editar os postos existentes. Será muito simples - já temos `postForm` e podemos utilizá-lo também para edição.

Vamos adicionar uma nova página `edit` ao `EditPresenter`:

```php .{file:app/Presenters/EditPresenter.php}
public function renderEdit(int $postId): void
{
	$post = $this->database
		->table('posts')
		->get($postId);

	if (!$post) {
		$this->error('Post not found');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}
```

E crie o modelo `Edit/edit.latte`:

```latte .{file:app/Presenters/templates/Edit/edit.latte}
{block content}
<h1>Edit post</h1>

{control postForm}
```

E atualizar o método `postFormSucceeded`, que poderá ou adicionar um novo post (como faz agora), ou editar os já existentes:

```php .{file:app/Presenters/EditPresenter.php}
private function postFormSucceeded(array $data): void
{
	$postId = $this->getParameter('postId');

	if ($postId) {
		$post = $this->database
			->table('posts')
			->get($postId);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Quando o parâmetro `postId` é fornecido, isso significa que um post está sendo editado. Nesse caso, verificaremos se o post realmente existe e, se for o caso, atualizá-lo-emos no banco de dados. Se o parâmetro `postId` não for fornecido, significa que um novo post será adicionado.

Mas de onde vem o `postId`? É o parâmetro passado para o método `renderEdit`.

Agora você pode adicionar um link para o modelo `app/Presenters/templates/Post/show.latte`:

```latte
<a n:href="Edit:edit $post->id">Edit this post</a>
```


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

O blog está funcionando, as pessoas estão comentando rapidamente e nós não confiamos mais no Adminer para adicionar novos posts. É totalmente independente e até mesmo pessoas normais podem postar lá. Mas espere, isso provavelmente não está bem, que qualquer pessoa, quero dizer, qualquer pessoa na Internet, possa postar em nosso blog. É necessária alguma forma de autenticação para que somente usuários logados possam postar. Vamos acrescentar isso no próximo capítulo.

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

Criação e Edição de Posts

Que grande momento. Temos um novo blog super legal, as pessoas estão discutindo nos comentários e finalmente temos algum tempo para mais programação. Embora gostemos de Adminer, não é tão confortável escrever nele posts de blogs. Talvez seja o momento certo para adicionar um formulário simples para adicionar novos posts diretamente de nosso aplicativo. Vamos fazer isso.

Vamos começar projetando a IU:

  1. Na página inicial, vamos adicionar um link „Escrever novo post“.
  2. Ele mostrará um formulário com título e área de texto para o conteúdo.
  3. Quando você clicar no botão Salvar, ele salvará o post do blog.

Mais tarde também adicionaremos autenticação e permitiremos apenas usuários logados para adicionar novos posts. Mas vamos fazer isso mais tarde. Que código precisaremos escrever para que funcione?

  1. Criar um novo apresentador com um formulário para adicionar postos.
  2. Definir uma chamada de retorno que será acionada após o envio bem sucedido do formulário e que salvará o novo post no banco de dados.
  3. Criar um novo modelo para o formulário.
  4. Adicionar um link para o formulário ao modelo da página principal.

Novo apresentador

Nomeie o novo apresentador EditPresenter e salve-o em app/Presenters/EditPresenter.php. Ele também precisa se conectar ao banco de dados, então aqui novamente escrevemos um construtor que exigirá uma conexão com o banco de dados:

<?php
namespace App\Presenters;

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

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

Formulário para salvar postes

Formulários e componentes já foram cobertos quando estávamos adicionando apoio para comentários. Se você estiver confuso sobre o tópico, vá verificar como os formulários e componentes funcionam novamente, nós esperaremos aqui ;)

Agora adicione este método ao EditPresenter:

protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Title:')
		->setRequired();
	$form->addTextArea('content', 'Content:')
		->setRequired();

	$form->addSubmit('send', 'Save and publish');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Salvando novos postos do formulário

Continue adicionando um método de manipulador.

private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}

Apenas uma explicação rápida: ele pega os valores do formulário, insere-os no banco de dados, cria uma mensagem para o usuário de que o post foi salvo com sucesso e redireciona para a página onde esse post é publicado para que você possa ver como ele se parece.

Página para criar um novo posto

Vamos apenas criar o modelo Edit/create.latte:

{block content}
<h1>New post</h1>

{control postForm}

Tudo já deve estar claro a esta altura. A última linha mostra a forma que estamos prestes a criar.

Poderíamos também criar um método renderCreate correspondente, mas não é necessário. Não precisamos obter nenhum dado do banco de dados e passá-lo para o modelo, para que esse método fique vazio. Nesses casos, o método pode não existir em absoluto.

Você provavelmente já sabe como adicionar um link para EditPresenter e sua ação create. Experimente-o.

Basta adicionar ao arquivo app/Presenters/templates/Home/default.latte:

<a n:href="Edit:create">Write new post</a>

Postos de edição

Vamos também acrescentar a capacidade de editar os postos existentes. Será muito simples – já temos postForm e podemos utilizá-lo também para edição.

Vamos adicionar uma nova página edit ao EditPresenter:

public function renderEdit(int $postId): void
{
	$post = $this->database
		->table('posts')
		->get($postId);

	if (!$post) {
		$this->error('Post not found');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}

E crie o modelo Edit/edit.latte:

{block content}
<h1>Edit post</h1>

{control postForm}

E atualizar o método postFormSucceeded, que poderá ou adicionar um novo post (como faz agora), ou editar os já existentes:

private function postFormSucceeded(array $data): void
{
	$postId = $this->getParameter('postId');

	if ($postId) {
		$post = $this->database
			->table('posts')
			->get($postId);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}

Quando o parâmetro postId é fornecido, isso significa que um post está sendo editado. Nesse caso, verificaremos se o post realmente existe e, se for o caso, atualizá-lo-emos no banco de dados. Se o parâmetro postId não for fornecido, significa que um novo post será adicionado.

Mas de onde vem o postId? É o parâmetro passado para o método renderEdit.

Agora você pode adicionar um link para o modelo app/Presenters/templates/Post/show.latte:

<a n:href="Edit:edit $post->id">Edit this post</a>

Sumário

O blog está funcionando, as pessoas estão comentando rapidamente e nós não confiamos mais no Adminer para adicionar novos posts. É totalmente independente e até mesmo pessoas normais podem postar lá. Mas espere, isso provavelmente não está bem, que qualquer pessoa, quero dizer, qualquer pessoa na Internet, possa postar em nosso blog. É necessária alguma forma de autenticação para que somente usuários logados possam postar. Vamos acrescentar isso no próximo capítulo.