Nette Documentation Preview

syntax
Ustvarjanje in urejanje objav
*****************************

Kako lepo je bilo. Imamo super kul nov blog, ljudje se prepirajo v komentarjih in končno imamo nekaj časa za več programiranja. Čeprav nam je Adminer všeč, pa pisanje blogovskih prispevkov v njem ni tako udobno. Morda je pravi čas, da dodamo preprost obrazec za dodajanje novih objav neposredno iz naše aplikacije. Naredimo to.

Začnimo z oblikovanjem uporabniškega vmesnika:

1. Na domači strani dodamo povezavo "Napiši novo objavo".
2. Prikazan bo obrazec z naslovom in besedilno površino za vsebino.
3. Ko kliknete gumb Shrani, bo shranil prispevek na spletnem dnevniku.

Pozneje bomo dodali tudi preverjanje pristnosti in omogočili dodajanje novih objav samo prijavljenim uporabnikom. Toda to storimo pozneje. Kakšno kodo bomo morali napisati, da bo to delovalo?

1. Ustvarite novo predstavitev z obrazcem za dodajanje objav.
2. Opredelite povratni klic, ki se bo sprožil po uspešni oddaji obrazca in ki bo novo objavo shranil v zbirko podatkov.
3. Ustvarite novo predlogo za obrazec.
4. Dodajte povezavo do obrazca v predlogo glavne strani.


Nov predvajalnik .[#toc-new-presenter]
======================================

Novemu predvajalniku damo ime `EditPresenter` in ga shranimo v `app/UI/Edit/`. Prav tako se mora povezati s podatkovno bazo, zato tudi tu napišemo konstruktor, ki bo zahteval povezavo s podatkovno bazo:

```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,
	) {
	}
}
```


Obrazec za shranjevanje objav .[#toc-form-for-saving-posts]
===========================================================

Obrazce in komponente smo že obravnavali, ko smo dodajali podporo za komentarje. Če ste zmedeni glede te teme, si ponovno oglejte, [kako delujejo obrazci in komponente |comments#form-for-commenting], mi pa bomo počakali tukaj ;)

Zdaj dodajte to metodo v `EditPresenter`:

```php .{file:app/UI/Edit/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;
}
```


Shranjevanje nove objave iz obrazca .[#toc-saving-new-post-from-form]
=====================================================================

Nadaljujte z dodajanjem metode Handler.

```php .{file:app/UI/Edit/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);
}
```

Samo kratka razlaga: iz obrazca pobere vrednosti, jih vstavi v zbirko podatkov, ustvari sporočilo za uporabnika, da je bila objava uspešno shranjena, in preusmeri na stran, kjer je ta objava objavljena, tako da si lahko ogledate, kako izgleda.


Stran za ustvarjanje nove objave .[#toc-page-for-creating-a-new-post]
=====================================================================

Ustvarimo samo predlogo `Edit/create.latte`:

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

{control postForm}
```

Zdaj bi moralo biti vse jasno. V zadnji vrstici je prikazan obrazec, ki ga bomo ustvarili.

Lahko bi ustvarili tudi ustrezno metodo `renderCreate`, vendar to ni potrebno. Ne potrebujemo namreč pridobiti nobenih podatkov iz podatkovne zbirke in jih posredovati predlogi, zato bi bila ta metoda prazna. V takšnih primerih metoda morda sploh ne bo obstajala.


Povezava za ustvarjanje objav .[#toc-link-for-creating-posts]
=============================================================

Verjetno že veste, kako dodati povezavo na `EditPresenter` in njeno akcijo `create`. Preizkusite jo.

Preprosto dodajte v datoteko `app/UI/Home/default.latte`:

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


Urejanje objav .[#toc-editing-posts]
====================================

Dodajmo tudi možnost urejanja obstoječih objav. To bo precej preprosto - že imamo `postForm` in ga lahko uporabimo tudi za urejanje.

Na spletno stran `EditPresenter` bomo dodali novo stran `edit`:

```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());
}
```

In ustvarili predlogo `Edit/edit.latte`:

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

{control postForm}
```

In posodobite metodo `postFormSucceeded`, s katero bo mogoče dodati novo objavo (kot zdaj) ali urediti obstoječo:

```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('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Če je podan parameter `id`, to pomeni, da se prispevek ureja. V takem primeru bomo preverili, ali objava res obstaja, in če je tako, jo bomo posodobili v zbirki podatkov. Če parameter `id` ni naveden, to pomeni, da bo dodana nova objava.

Toda od kod prihaja podatek `id`? To je parameter, ki ga posredujemo metodi `renderEdit`.

Zdaj lahko dodate povezavo do predloge `app/UI/Post/show.latte`:

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


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

Blog deluje, ljudje hitro komentirajo in pri dodajanju novih objav nismo več odvisni od Adminerja. Blog je popolnoma neodvisen in vanj lahko objavljajo tudi običajni ljudje. Ampak čakajte, to verjetno ni v redu, da lahko vsakdo, mislim res vsakdo na internetu, objavlja na našem blogu. Potrebna je neka oblika avtentikacije, tako da bi lahko objavljali le prijavljeni uporabniki. To bomo dodali v naslednjem poglavju.

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

Ustvarjanje in urejanje objav

Kako lepo je bilo. Imamo super kul nov blog, ljudje se prepirajo v komentarjih in končno imamo nekaj časa za več programiranja. Čeprav nam je Adminer všeč, pa pisanje blogovskih prispevkov v njem ni tako udobno. Morda je pravi čas, da dodamo preprost obrazec za dodajanje novih objav neposredno iz naše aplikacije. Naredimo to.

Začnimo z oblikovanjem uporabniškega vmesnika:

  1. Na domači strani dodamo povezavo „Napiši novo objavo“.
  2. Prikazan bo obrazec z naslovom in besedilno površino za vsebino.
  3. Ko kliknete gumb Shrani, bo shranil prispevek na spletnem dnevniku.

Pozneje bomo dodali tudi preverjanje pristnosti in omogočili dodajanje novih objav samo prijavljenim uporabnikom. Toda to storimo pozneje. Kakšno kodo bomo morali napisati, da bo to delovalo?

  1. Ustvarite novo predstavitev z obrazcem za dodajanje objav.
  2. Opredelite povratni klic, ki se bo sprožil po uspešni oddaji obrazca in ki bo novo objavo shranil v zbirko podatkov.
  3. Ustvarite novo predlogo za obrazec.
  4. Dodajte povezavo do obrazca v predlogo glavne strani.

Nov predvajalnik

Novemu predvajalniku damo ime EditPresenter in ga shranimo v app/UI/Edit/. Prav tako se mora povezati s podatkovno bazo, zato tudi tu napišemo konstruktor, ki bo zahteval povezavo s podatkovno bazo:

<?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,
	) {
	}
}

Obrazec za shranjevanje objav

Obrazce in komponente smo že obravnavali, ko smo dodajali podporo za komentarje. Če ste zmedeni glede te teme, si ponovno oglejte, kako delujejo obrazci in komponente, mi pa bomo počakali tukaj ;)

Zdaj dodajte to metodo v 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;
}

Shranjevanje nove objave iz obrazca

Nadaljujte z dodajanjem metode Handler.

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);
}

Samo kratka razlaga: iz obrazca pobere vrednosti, jih vstavi v zbirko podatkov, ustvari sporočilo za uporabnika, da je bila objava uspešno shranjena, in preusmeri na stran, kjer je ta objava objavljena, tako da si lahko ogledate, kako izgleda.

Stran za ustvarjanje nove objave

Ustvarimo samo predlogo Edit/create.latte:

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

{control postForm}

Zdaj bi moralo biti vse jasno. V zadnji vrstici je prikazan obrazec, ki ga bomo ustvarili.

Lahko bi ustvarili tudi ustrezno metodo renderCreate, vendar to ni potrebno. Ne potrebujemo namreč pridobiti nobenih podatkov iz podatkovne zbirke in jih posredovati predlogi, zato bi bila ta metoda prazna. V takšnih primerih metoda morda sploh ne bo obstajala.

Verjetno že veste, kako dodati povezavo na EditPresenter in njeno akcijo create. Preizkusite jo.

Preprosto dodajte v datoteko app/UI/Home/default.latte:

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

Urejanje objav

Dodajmo tudi možnost urejanja obstoječih objav. To bo precej preprosto – že imamo postForm in ga lahko uporabimo tudi za urejanje.

Na spletno stran EditPresenter bomo dodali novo stran edit:

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());
}

In ustvarili predlogo Edit/edit.latte:

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

{control postForm}

In posodobite metodo postFormSucceeded, s katero bo mogoče dodati novo objavo (kot zdaj) ali urediti obstoječo:

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('Post was published', 'success');
	$this->redirect('Post:show', $post->id);
}

Če je podan parameter id, to pomeni, da se prispevek ureja. V takem primeru bomo preverili, ali objava res obstaja, in če je tako, jo bomo posodobili v zbirki podatkov. Če parameter id ni naveden, to pomeni, da bo dodana nova objava.

Toda od kod prihaja podatek id? To je parameter, ki ga posredujemo metodi renderEdit.

Zdaj lahko dodate povezavo do predloge app/UI/Post/show.latte:

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

Povzetek

Blog deluje, ljudje hitro komentirajo in pri dodajanju novih objav nismo več odvisni od Adminerja. Blog je popolnoma neodvisen in vanj lahko objavljajo tudi običajni ljudje. Ampak čakajte, to verjetno ni v redu, da lahko vsakdo, mislim res vsakdo na internetu, objavlja na našem blogu. Potrebna je neka oblika avtentikacije, tako da bi lahko objavljali le prijavljeni uporabniki. To bomo dodali v naslednjem poglavju.