Nette Documentation Preview

syntax
Megjegyzések
************

A blogot beüzemeltük, írtunk néhány nagyon jó blogbejegyzést és közzétettük őket az Adminer-en keresztül. Az emberek olvassák a blogot, és nagyon lelkesek az ötleteink iránt. Naponta sok dicsérő e-mailt kapunk. De mire jó ez a sok dicséret, ha csak e-mailben kaptuk meg, így senki más nem tudja elolvasni? Nem lenne jobb, ha az emberek közvetlenül a blogon tudnának hozzászólni, hogy mindenki más is olvashassa, milyen nagyszerűek vagyunk?

Tegyük az összes cikket kommentelhetővé.


Új táblázat létrehozása .[#toc-creating-a-new-table]
====================================================

Indítsa el újra az Adminer programot, és hozzon létre egy új táblát `comments` néven ezekkel az oszlopokkal:

- `id` int, check autoincrement (AI)
- `post_id`, idegen kulcs, amely a `posts` táblára hivatkozik.
- `name` varchar, hossza 255
- `email` varchar, hossza 255
- `content` text
- `created_at` timestamp

Így kell kinéznie:

[* adminer-comments.webp *]

Ne felejtsd el használni az InnoDB tábla tárolását, és nyomd meg a Mentés gombot.

```sql
CREATE TABLE `comments` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`post_id` int(11) NOT NULL,
	`name` varchar(250) NOT NULL,
	`email` varchar(250) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
) ENGINE=InnoDB CHARSET=utf8;
```


Formanyomtatvány a hozzászóláshoz .[#toc-form-for-commenting]
=============================================================

Először is létre kell hoznunk egy űrlapot, amely lehetővé teszi a felhasználók számára, hogy hozzászóljanak az oldalunkhoz. A Nette Framework fantasztikusan támogatja az űrlapokat. Ezeket egy prezenterben lehet konfigurálni és egy sablonban megjeleníteni.

A Nette Framework rendelkezik a *komponensek* fogalmával. A **komponens** egy újrafelhasználható osztály vagy kódrészlet, amely egy másik komponenshez csatolható. Még a prezenter is egy komponens. Minden komponens a komponens gyár segítségével jön létre. Definiáljuk tehát a `PostPresenter` oldalon a comments form factory-t .

```php .{file:app/UI/Post/PostPresenter.php}
protected function createComponentCommentForm(): Form
{
	$form = new Form; // jelentése: Nette\Application\UI\Form

	$form->addText('name', 'Az Ön neve:')
		->setRequired();

	$form->addEmail('email', 'Email:');

	$form->addTextArea('content', 'Megjegyzés:')
		->setRequired();

	$form->addSubmit('send', 'Publish comment');

	return $form;
}
```

Magyarázzuk el egy kicsit. Az első sor létrehoz egy új példányt a `Form` komponensből. A következő metódusok HTML-bemeneteket csatolnak az űrlap definíciójához. `->addText` a következő formában jelenik meg `<input type=text name=name>`, a `<label>Your name:</label>`. Ahogy már most kitalálhattad, a `->addTextArea` csatol egy `<textarea>` és a `->addSubmit` hozzáad egy `<input type=submit>`. Több ilyen módszer is van, de most csak ennyit kell tudnod. [Többet megtudhatsz a dokumentációban |forms:].

Miután az űrlapkomponens definiálva van egy prezenterben, megjeleníthetjük (megjeleníthetjük) egy sablonban. Ehhez helyezze a `{control}` címkét a poszt részlet sablonjának végére, a `Post/show.latte`. Mivel a komponens neve `commentForm` (a `createComponentCommentForm` metódus nevéből származik), a címke így fog kinézni

```latte .{file:app/UI/Post/show.latte}
...
<h2>Post new comment</h2>

{control commentForm}
```

Most, ha megnézzük valamelyik bejegyzés részletét, egy új űrlapot fogunk találni a hozzászólások írásához.


Mentés az adatbázisba .[#toc-saving-to-database]
================================================

Próbált már adatokat elküldeni? Bizonyára észrevette, hogy az űrlap nem hajt végre semmilyen műveletet. Csak ott van, jól néz ki, de nem csinál semmit. Egy callback metódust kell hozzá csatolnunk, amely elmenti a beküldött adatokat.

Helyezzük a következő sort a `return` sor elé a `commentForm` komponens gyárában:

```php
$form->onSuccess[] = $this->commentFormSucceeded(...);
```

Ez azt jelenti, hogy "az űrlap sikeres elküldése után hívja meg az aktuális prezenter `commentFormSucceeded` metódusát". Ez a metódus még nem létezik, ezért hozzuk létre.

```php .{file:app/UI/Post/PostPresenter.php}
private function commentFormSucceeded(\stdClass $data): void
{
	$id = $this->getParameter('id');

	$this->database->table('comments')->insert([
		'post_id' => $id,
		'name' => $data->name,
		'email' => $data->email,
		'content' => $data->content,
	]);

	$this->flashMessage('Thank you for your comment', 'success');
	$this->redirect('this');
}
```

Rögtön a `commentForm` komponensgyár után kell elhelyeznünk.

Az új metódusnak egy argumentuma van, ami a beküldendő űrlap példánya, amelyet a komponensgyár hozott létre. A benyújtott értékeket a `$data` címen kapjuk meg. Ezután pedig beszúrjuk az adatokat az `comments` adatbázis táblába.

Még két metódushívást kell elmagyarázni. A redirect szó szerint átirányít az aktuális oldalra. Ezt minden alkalommal meg kell tennünk, amikor az űrlapot elküldtük, érvényes, és a callback művelet megtette, amit kellett volna. Továbbá, ha az űrlap elküldése után átirányítod az oldalt, nem fogod látni a jól ismert `Would you like to submit the post data again?` üzenetet, amelyet néha láthatsz a böngészőben. (Általánosságban elmondható, hogy egy űrlap `POST` módszerrel történő elküldése után mindig át kell irányítania a felhasználót a `GET` műveletre).

A `flashMessage` arra szolgál, hogy tájékoztassa a felhasználót valamilyen művelet eredményéről. Mivel átirányítunk, az üzenetet nem lehet közvetlenül a sablonhoz átadni és megjeleníteni. Ezért van ez a metódus, amely tárolja és a következő oldalbetöltéskor elérhetővé teszi. A flash üzeneteket az alapértelmezett `app/UI/@layout.latte` fájlban rendereljük, és ez így néz ki:

```latte
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
	{$flash->message}
</div>
```

Mint már tudjuk, automatikusan átkerülnek a sablonba, így nem kell sokat gondolkodni rajta, egyszerűen csak működik. További részletekért [nézd meg a dokumentációt |application:presenters#flash-messages].


A megjegyzések megjelenítése .[#toc-rendering-the-comments]
===========================================================

Ez az egyik olyan dolog, amit egyszerűen imádni fogsz. A Nette adatbázisnak van ez a menő funkciója, amit úgy hívnak, hogy [Explorer |database:explorer]. Emlékszel, hogy a táblákat InnoDB-ként hoztuk létre? Az Adminer létrehozta az úgynevezett [idegen kulcsokat |https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html], amelyek rengeteg munkát takarítanak meg nekünk.

A Nette Database Explorer az idegen kulcsokat használja a táblák közötti kapcsolatok feloldására, és a kapcsolatok ismeretében automatikusan lekérdezéseket tud létrehozni számodra.

Mint emlékezhetsz, a `$post` változót átadtuk a sablonban a `PostPresenter::renderShow()`, és most szeretnénk végigmenni az összes olyan megjegyzésen, amelynek a `post_id` oszlopa megegyezik a mi `$post->id`-unkkal . Ezt a `$post->related('comments')` meghívásával teheti meg. Ez ilyen egyszerű. Nézze meg a kapott kódot.

```php .{file:app/UI/Post/PostPresenter.php}
public function renderShow(int $id): void
{
	...
	$this->template->post = $post;
	$this->template->comments = $post->related('comments')->order('created_at');
}
```

És a sablont:

```latte .{file:app/UI/Post/show.latte}
...
<h2>Comments</h2>

<div class="comments">
	{foreach $comments as $comment}
		<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
			{$comment->name}
		</a></b> said:</p>

		<div>{$comment->content}</div>
	{/foreach}
</div>
...
```

Figyeljük meg a speciális `n:tag-if` attribútumot. Már tudod, hogyan működik a `n: attributes`. Nos, ha az attribútum elé a `tag-` attribútumot írja, az csak a címkéket fogja körbeölelni, a tartalmukat nem. Ez lehetővé teszi, hogy a hozzászóló nevét linkké alakítsa, ha megadta az e-mail címét. Ez a két sor azonos eredményt ad:

```latte
<strong n:tag-if="$important"> Hello there! </strong>

{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}
```

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

Megjegyzések

A blogot beüzemeltük, írtunk néhány nagyon jó blogbejegyzést és közzétettük őket az Adminer-en keresztül. Az emberek olvassák a blogot, és nagyon lelkesek az ötleteink iránt. Naponta sok dicsérő e-mailt kapunk. De mire jó ez a sok dicséret, ha csak e-mailben kaptuk meg, így senki más nem tudja elolvasni? Nem lenne jobb, ha az emberek közvetlenül a blogon tudnának hozzászólni, hogy mindenki más is olvashassa, milyen nagyszerűek vagyunk?

Tegyük az összes cikket kommentelhetővé.

Új táblázat létrehozása

Indítsa el újra az Adminer programot, és hozzon létre egy új táblát comments néven ezekkel az oszlopokkal:

  • id int, check autoincrement (AI)
  • post_id, idegen kulcs, amely a posts táblára hivatkozik.
  • name varchar, hossza 255
  • email varchar, hossza 255
  • content text
  • created_at timestamp

Így kell kinéznie:

Ne felejtsd el használni az InnoDB tábla tárolását, és nyomd meg a Mentés gombot.

CREATE TABLE `comments` (
	`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`post_id` int(11) NOT NULL,
	`name` varchar(250) NOT NULL,
	`email` varchar(250) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
	FOREIGN KEY (`post_id`) REFERENCES `posts` (`id`)
) ENGINE=InnoDB CHARSET=utf8;

Formanyomtatvány a hozzászóláshoz

Először is létre kell hoznunk egy űrlapot, amely lehetővé teszi a felhasználók számára, hogy hozzászóljanak az oldalunkhoz. A Nette Framework fantasztikusan támogatja az űrlapokat. Ezeket egy prezenterben lehet konfigurálni és egy sablonban megjeleníteni.

A Nette Framework rendelkezik a komponensek fogalmával. A komponens egy újrafelhasználható osztály vagy kódrészlet, amely egy másik komponenshez csatolható. Még a prezenter is egy komponens. Minden komponens a komponens gyár segítségével jön létre. Definiáljuk tehát a PostPresenter oldalon a comments form factory-t .

protected function createComponentCommentForm(): Form
{
	$form = new Form; // jelentése: Nette\Application\UI\Form

	$form->addText('name', 'Az Ön neve:')
		->setRequired();

	$form->addEmail('email', 'Email:');

	$form->addTextArea('content', 'Megjegyzés:')
		->setRequired();

	$form->addSubmit('send', 'Publish comment');

	return $form;
}

Magyarázzuk el egy kicsit. Az első sor létrehoz egy új példányt a Form komponensből. A következő metódusok HTML-bemeneteket csatolnak az űrlap definíciójához. ->addText a következő formában jelenik meg <input type=text name=name>, a <label>Your name:</label>. Ahogy már most kitalálhattad, a ->addTextArea csatol egy <textarea> és a ->addSubmit hozzáad egy <input type=submit>. Több ilyen módszer is van, de most csak ennyit kell tudnod. Többet megtudhatsz a dokumentációban.

Miután az űrlapkomponens definiálva van egy prezenterben, megjeleníthetjük (megjeleníthetjük) egy sablonban. Ehhez helyezze a {control} címkét a poszt részlet sablonjának végére, a Post/show.latte. Mivel a komponens neve commentForm (a createComponentCommentForm metódus nevéből származik), a címke így fog kinézni

...
<h2>Post new comment</h2>

{control commentForm}

Most, ha megnézzük valamelyik bejegyzés részletét, egy új űrlapot fogunk találni a hozzászólások írásához.

Mentés az adatbázisba

Próbált már adatokat elküldeni? Bizonyára észrevette, hogy az űrlap nem hajt végre semmilyen műveletet. Csak ott van, jól néz ki, de nem csinál semmit. Egy callback metódust kell hozzá csatolnunk, amely elmenti a beküldött adatokat.

Helyezzük a következő sort a return sor elé a commentForm komponens gyárában:

$form->onSuccess[] = $this->commentFormSucceeded(...);

Ez azt jelenti, hogy „az űrlap sikeres elküldése után hívja meg az aktuális prezenter commentFormSucceeded metódusát“. Ez a metódus még nem létezik, ezért hozzuk létre.

private function commentFormSucceeded(\stdClass $data): void
{
	$id = $this->getParameter('id');

	$this->database->table('comments')->insert([
		'post_id' => $id,
		'name' => $data->name,
		'email' => $data->email,
		'content' => $data->content,
	]);

	$this->flashMessage('Thank you for your comment', 'success');
	$this->redirect('this');
}

Rögtön a commentForm komponensgyár után kell elhelyeznünk.

Az új metódusnak egy argumentuma van, ami a beküldendő űrlap példánya, amelyet a komponensgyár hozott létre. A benyújtott értékeket a $data címen kapjuk meg. Ezután pedig beszúrjuk az adatokat az comments adatbázis táblába.

Még két metódushívást kell elmagyarázni. A redirect szó szerint átirányít az aktuális oldalra. Ezt minden alkalommal meg kell tennünk, amikor az űrlapot elküldtük, érvényes, és a callback művelet megtette, amit kellett volna. Továbbá, ha az űrlap elküldése után átirányítod az oldalt, nem fogod látni a jól ismert Would you like to submit the post data again? üzenetet, amelyet néha láthatsz a böngészőben. (Általánosságban elmondható, hogy egy űrlap POST módszerrel történő elküldése után mindig át kell irányítania a felhasználót a GET műveletre).

A flashMessage arra szolgál, hogy tájékoztassa a felhasználót valamilyen művelet eredményéről. Mivel átirányítunk, az üzenetet nem lehet közvetlenül a sablonhoz átadni és megjeleníteni. Ezért van ez a metódus, amely tárolja és a következő oldalbetöltéskor elérhetővé teszi. A flash üzeneteket az alapértelmezett app/UI/@layout.latte fájlban rendereljük, és ez így néz ki:

<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
	{$flash->message}
</div>

Mint már tudjuk, automatikusan átkerülnek a sablonba, így nem kell sokat gondolkodni rajta, egyszerűen csak működik. További részletekért nézd meg a dokumentációt.

A megjegyzések megjelenítése

Ez az egyik olyan dolog, amit egyszerűen imádni fogsz. A Nette adatbázisnak van ez a menő funkciója, amit úgy hívnak, hogy Explorer. Emlékszel, hogy a táblákat InnoDB-ként hoztuk létre? Az Adminer létrehozta az úgynevezett idegen kulcsokat, amelyek rengeteg munkát takarítanak meg nekünk.

A Nette Database Explorer az idegen kulcsokat használja a táblák közötti kapcsolatok feloldására, és a kapcsolatok ismeretében automatikusan lekérdezéseket tud létrehozni számodra.

Mint emlékezhetsz, a $post változót átadtuk a sablonban a PostPresenter::renderShow(), és most szeretnénk végigmenni az összes olyan megjegyzésen, amelynek a post_id oszlopa megegyezik a mi $post->id-unkkal . Ezt a $post->related('comments') meghívásával teheti meg. Ez ilyen egyszerű. Nézze meg a kapott kódot.

public function renderShow(int $id): void
{
	...
	$this->template->post = $post;
	$this->template->comments = $post->related('comments')->order('created_at');
}

És a sablont:

...
<h2>Comments</h2>

<div class="comments">
	{foreach $comments as $comment}
		<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
			{$comment->name}
		</a></b> said:</p>

		<div>{$comment->content}</div>
	{/foreach}
</div>
...

Figyeljük meg a speciális n:tag-if attribútumot. Már tudod, hogyan működik a n: attributes. Nos, ha az attribútum elé a tag- attribútumot írja, az csak a címkéket fogja körbeölelni, a tartalmukat nem. Ez lehetővé teszi, hogy a hozzászóló nevét linkké alakítsa, ha megadta az e-mail címét. Ez a két sor azonos eredményt ad:

<strong n:tag-if="$important"> Hello there! </strong>

{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}