Nette Documentation Preview

syntax
Tworzenie i edycja postów
*************************

To jest niesamowite! Mamy super fajnego nowego bloga, ludzie wściekle dyskutują w komentarzach, a my w końcu mamy trochę czasu, żeby jeszcze trochę poprogramować. O ile Adminer jest świetnym narzędziem, to do pisania nowych postów na blogu nie jest do końca idealny. To chyba dobry moment, aby stworzyć prosty formularz do dodawania nowych postów bezpośrednio z aplikacji. Zróbmy to.

Zacznijmy od zaprojektowania interfejsu użytkownika:

1) Na stronie głównej dodamy link "Napisz nowy post".
2. Ten link wyświetli formularz z tytułem i obszarem tekstowym dla treści postu.
3. Gdy klikniemy przycisk Save, post zostanie zapisany w bazie danych.

Później dodamy również logowanie i pozwolimy tylko zalogowanym użytkownikom dodawać posty. Ale to na później. Jaki kod musimy teraz napisać, aby wszystko działało?

1. Stworzymy nowy prezenter z formularzem do dodawania postów.
2. Zdefiniuj callback, który zostanie uruchomiony, gdy formularz zostanie pomyślnie przesłany i który zapisze nowy post do bazy danych.
3. Tworzymy nowy szablon, na którym będzie umieszczony formularz.
4. Dodaj link do formularza do szablonu strony głównej.


Nowy prezenter .[#toc-new-presenter]
====================================

Nowy prezenter będzie się nazywał `EditPresenter` i będzie przechowywany w `app/UI/Edit/`. Musi również połączyć się z bazą danych, więc ponownie napiszemy tutaj konstruktor, który będzie wymagał połączenia z bazą danych:

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

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

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


Formularz do zapisywania składek .[#toc-form-for-saving-posts]
==============================================================

Formy i komponenty wyjaśniliśmy już przy okazji tworzenia komentarzy. Jeśli nadal nie jest to jasne, przejdź przez [tworzenie formularzy i komponentów |comments#Form-for-Commenting], my tu na razie poczekamy ;)

Teraz dodajmy tę metodę do prezentera `EditPresenter`:

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

	$form->addSubmit('send', 'Uložit a publikovat');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}
```


Zapisywanie nowego postu z poziomu formularza .[#toc-saving-new-post-from-form]
===============================================================================

Dalej dodajemy metodę, która przetwarza dane z formularza:

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

	$this->flashMessage("Příspěvek byl úspěšně publikován.", 'success');
	$this->redirect('Post:show', $post->id);
}
```

Krótkie podsumowanie: metoda ta pobiera dane z formularza, umieszcza je w bazie danych, tworzy wiadomość dla użytkownika, gdy post zostanie pomyślnie zapisany, i przekierowuje na stronę z nowym postem, więc zaraz zobaczymy, jak to wygląda.


Strona do tworzenia nowego postu .[#toc-page-for-creating-a-new-post]
=====================================================================

Utwórzmy teraz szablon `Edit/create.latte`:

```latte .{file:app/UI/Edit/create.latte}
{block content}
<h1>Nový příspěvek</h1>

{control postForm}
```

Wszystko powinno być już jasne. Ostatnia linijka oddaje formę, którą dopiero mamy stworzyć.

Moglibyśmy również stworzyć odpowiednią metodę `renderCreate`, ale nie jest to konieczne. Nie potrzebujemy pobierać żadnych danych z bazy i przekazywać ich do szablonu, więc metoda byłaby pusta. W takich przypadkach metoda może w ogóle nie istnieć.


Link do tworzenia postów .[#toc-link-for-creating-posts]
========================================================

Zapewne już wiesz jak dodać link do strony `EditPresenter` i jej akcji `create`. Wypróbuj to.

Wystarczy dodać `app/UI/Home/default.latte` do pliku:

```latte
<a n:href="Edit:create">Napsat nový příspěvek</a>
```


Edytuj posty .[#toc-editing-posts]
==================================

Teraz dodamy również możliwość edycji postu. To będzie bardzo proste. Mamy już formularz `postForm` i możemy go wykorzystać do edycji.

Dodamy nową stronę `edit` do prezentera `EditPresenter`:

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

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

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

I utwórz kolejny szablon `Edit/edit.latte`:

```latte .{file:app/UI/Edit/edit.latte}
{block content}
<h1>Upravit příspěvek</h1>

{control postForm}
```

I zmodyfikuj metodę `postFormSucceeded`, aby można było zarówno dodać nowy artykuł (tak jak teraz), jak i edytować istniejący:

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

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

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

	$this->flashMessage('Příspěvek byl úspěšně publikován.', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Jeśli parametr `id` jest dostępny , oznacza to, że będziemy edytować post. W takim przypadku sprawdzimy, czy żądany post naprawdę istnieje, a jeśli tak, zaktualizuj go w bazie danych. Jeśli parametr `id` nie jest dostępny, oznacza to, że należy dodać nowy post.

Skąd jednak bierze się parametr `id`? Jest to parametr, który został wstawiony do metody `renderEdit`.

Teraz możemy dodać link do szablonu `app/UI/Post/show.latte`:

```latte
<a n:href="Edit:edit $post->id">Upravit příspěvek</a>
```


Podsumowanie .[#toc-summary]
============================

Blog już działa, goście aktywnie go komentują i nie potrzebujemy już Adminera do jego publikacji. Aplikacja jest w pełni niezależna i każdy może dodać nowy post. Więc zaraz, chyba nie do końca jest tak, że każdy - i naprawdę mam na myśli każdego z dostępem do internetu - może dodawać nowe posty. Potrzebne są pewne zabezpieczenia, aby tylko zalogowany użytkownik mógł dodać nowy post. Przyjrzymy się temu w następnym rozdziale.

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

Tworzenie i edycja postów

To jest niesamowite! Mamy super fajnego nowego bloga, ludzie wściekle dyskutują w komentarzach, a my w końcu mamy trochę czasu, żeby jeszcze trochę poprogramować. O ile Adminer jest świetnym narzędziem, to do pisania nowych postów na blogu nie jest do końca idealny. To chyba dobry moment, aby stworzyć prosty formularz do dodawania nowych postów bezpośrednio z aplikacji. Zróbmy to.

Zacznijmy od zaprojektowania interfejsu użytkownika:

  1. Na stronie głównej dodamy link „Napisz nowy post“.

2. Ten link wyświetli formularz z tytułem i obszarem tekstowym dla treści postu. 3. Gdy klikniemy przycisk Save, post zostanie zapisany w bazie danych.

Później dodamy również logowanie i pozwolimy tylko zalogowanym użytkownikom dodawać posty. Ale to na później. Jaki kod musimy teraz napisać, aby wszystko działało?

  1. Stworzymy nowy prezenter z formularzem do dodawania postów.
  2. Zdefiniuj callback, który zostanie uruchomiony, gdy formularz zostanie pomyślnie przesłany i który zapisze nowy post do bazy danych.
  3. Tworzymy nowy szablon, na którym będzie umieszczony formularz.
  4. Dodaj link do formularza do szablonu strony głównej.

Nowy prezenter

Nowy prezenter będzie się nazywał EditPresenter i będzie przechowywany w app/UI/Edit/. Musi również połączyć się z bazą danych, więc ponownie napiszemy tutaj konstruktor, który będzie wymagał połączenia z bazą danych:

<?php
namespace App\UI\Edit;

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

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

Formularz do zapisywania składek

Formy i komponenty wyjaśniliśmy już przy okazji tworzenia komentarzy. Jeśli nadal nie jest to jasne, przejdź przez tworzenie formularzy i komponentów, my tu na razie poczekamy ;)

Teraz dodajmy tę metodę do prezentera EditPresenter:

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

	$form->addSubmit('send', 'Uložit a publikovat');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Zapisywanie nowego postu z poziomu formularza

Dalej dodajemy metodę, która przetwarza dane z formularza:

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

	$this->flashMessage("Příspěvek byl úspěšně publikován.", 'success');
	$this->redirect('Post:show', $post->id);
}

Krótkie podsumowanie: metoda ta pobiera dane z formularza, umieszcza je w bazie danych, tworzy wiadomość dla użytkownika, gdy post zostanie pomyślnie zapisany, i przekierowuje na stronę z nowym postem, więc zaraz zobaczymy, jak to wygląda.

Strona do tworzenia nowego postu

Utwórzmy teraz szablon Edit/create.latte:

{block content}
<h1>Nový příspěvek</h1>

{control postForm}

Wszystko powinno być już jasne. Ostatnia linijka oddaje formę, którą dopiero mamy stworzyć.

Moglibyśmy również stworzyć odpowiednią metodę renderCreate, ale nie jest to konieczne. Nie potrzebujemy pobierać żadnych danych z bazy i przekazywać ich do szablonu, więc metoda byłaby pusta. W takich przypadkach metoda może w ogóle nie istnieć.

Zapewne już wiesz jak dodać link do strony EditPresenter i jej akcji create. Wypróbuj to.

Wystarczy dodać app/UI/Home/default.latte do pliku:

<a n:href="Edit:create">Napsat nový příspěvek</a>

Edytuj posty

Teraz dodamy również możliwość edycji postu. To będzie bardzo proste. Mamy już formularz postForm i możemy go wykorzystać do edycji.

Dodamy nową stronę edit do prezentera EditPresenter:

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

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

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

I utwórz kolejny szablon Edit/edit.latte:

{block content}
<h1>Upravit příspěvek</h1>

{control postForm}

I zmodyfikuj metodę postFormSucceeded, aby można było zarówno dodać nowy artykuł (tak jak teraz), jak i edytować istniejący:

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

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

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

	$this->flashMessage('Příspěvek byl úspěšně publikován.', 'success');
	$this->redirect('Post:show', $post->id);
}

Jeśli parametr id jest dostępny , oznacza to, że będziemy edytować post. W takim przypadku sprawdzimy, czy żądany post naprawdę istnieje, a jeśli tak, zaktualizuj go w bazie danych. Jeśli parametr id nie jest dostępny, oznacza to, że należy dodać nowy post.

Skąd jednak bierze się parametr id? Jest to parametr, który został wstawiony do metody renderEdit.

Teraz możemy dodać link do szablonu app/UI/Post/show.latte:

<a n:href="Edit:edit $post->id">Upravit příspěvek</a>

Podsumowanie

Blog już działa, goście aktywnie go komentują i nie potrzebujemy już Adminera do jego publikacji. Aplikacja jest w pełni niezależna i każdy może dodać nowy post. Więc zaraz, chyba nie do końca jest tak, że każdy – i naprawdę mam na myśli każdego z dostępem do internetu – może dodawać nowe posty. Potrzebne są pewne zabezpieczenia, aby tylko zalogowany użytkownik mógł dodać nowy post. Przyjrzymy się temu w następnym rozdziale.