Kommentek
Feltöltöttük a blogot a webszerverre, és közzétettünk néhány nagyon érdekes bejegyzést az Adminer segítségével. Az emberek olvassák a blogunkat, és nagyon lelkesek érte. Minden nap sok dicsérő e-mailt kapunk. De mit ér ez a sok dicséret, ha csak e-mailben van meg, és senki sem olvashatja el? Jobb lenne, ha az olvasó közvetlenül kommentelhetné a cikket, így mindenki elolvashatná, milyen csodálatosak vagyunk.
Tehát programozzunk kommenteket.
Új tábla létrehozása
Indítsuk el az Adminert, és hozzunk létre egy comments
táblát a következő oszlopokkal:
id
int, jelöljük be az autoincrement-et (AI)post_id
, idegen kulcs, amely aposts
táblára hivatkozikname
varchar, length 255email
varchar, length 255content
textcreated_at
timestamp
A táblának tehát valahogy így kell kinéznie:

Ne felejtse el újra az InnoDB tárolót használni.
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;
Kommentálási űrlap
Először létre kell hoznunk egy űrlapot, amely lehetővé teszi a felhasználók számára a bejegyzések kommentálását. A Nette Framework csodálatos támogatást nyújt az űrlapokhoz. Konfigurálhatjuk őket a presenterben, és megjeleníthetjük a sablonban.
A Nette Framework a komponensek koncepcióját használja. A komponens egy újra felhasználható osztály vagy
kódrészlet, amely egy másik komponenshez csatolható. Még a presenter is egy komponens. Minden komponenst egy factory hoz
létre. Tehát létrehozunk egy factory-t a komment űrlaphoz a PostPresenter
-ben.
protected function createComponentCommentForm(): Form
{
$form = new Form; // means Nette\Application\UI\Form
$form->addText('name', 'Név:')
->setRequired();
$form->addEmail('email', 'E-mail:');
$form->addTextArea('content', 'Komment:')
->setRequired();
$form->addSubmit('send', 'Komment közzététele');
return $form;
}
Magyarázzuk el ezt is egy kicsit. Az első sor létrehoz egy új Form
komponens példányt. A következő
metódusok HTML inputokat csatolnak ennek az űrlapnak a definíciójához. A ->addText
<input type="text" name="name">
-ként jelenik meg <label>Név:</label>
-lel. Ahogy
valószínűleg helyesen sejti, a ->addTextArea
<textarea>
-ként, a ->addSubmit
pedig <input type="submit">
-ként jelenik meg. Sokkal több hasonló metódus létezik, de ezek egyelőre
elegendőek ehhez az űrlaphoz. Többet a dokumentációban olvashat.
Ha az űrlap már definiálva van a presenterben, megjeleníthetjük (kirajzolhatjuk) a sablonban. Ezt úgy tehetjük meg, hogy
a {control}
taget elhelyezzük a sablon végén, amely egy konkrét bejegyzést jelenít meg, a
Post/show.latte
-ban. Mivel a komponens neve commentForm
(a név a
createComponentCommentForm
metódus nevéből származik), a tag így fog kinézni:
...
<h2>Új komment hozzáadása</h2>
{control commentForm}
Ha most megtekinti a bejegyzés részleteit tartalmazó oldalt, annak végén látni fogja az új komment űrlapot.
Mentés az adatbázisba
Próbálta már kitölteni és elküldeni az űrlapot? Valószínűleg észrevette, hogy az űrlap valójában semmit sem csinál. Csatolnunk kell egy callback metódust, amely elmenti az elküldött adatokat.
A return
előtti sorba a commentForm
komponens factory-jában helyezzük el a következő sort:
$form->onSuccess[] = $this->commentFormSucceeded(...);
Az előző írásmód azt jelenti, hogy “az űrlap sikeres elküldése után hívd meg a commentFormSucceeded
metódust a jelenlegi presenterből”. Ez a metódus azonban még nem létezik. Hozzuk létre tehát:
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('Köszönöm a kommentet', 'success');
$this->redirect('this');
}
Ezt a metódust közvetlenül a commentForm
űrlap factory-ja után helyezzük el.
Ennek az új metódusnak egy argumentuma van, ami az elküldött űrlap példánya – amelyet a factory hozott létre. Az
elküldött értékeket a $data
-ban kapjuk meg. Ezután az adatokat elmentjük a comments
adatbázis
táblába.
Van még két másik metódus, amelyek magyarázatot érdemelnek. A redirect metódus szó szerint visszairányít az
aktuális oldalra. Ezt célszerű minden űrlap elküldése után megtenni, ha érvényes adatokat tartalmazott, és a callback a
műveletet a tervek szerint hajtotta végre. Továbbá, ha az űrlap elküldése után átirányítjuk az oldalt, nem fogjuk
látni a jól ismert Szeretné újra elküldeni az űrlap adatait?
üzenetet, amelyet néha a böngészőben
láthatunk. (Általában az űrlap POST
metódussal történő elküldése után mindig átirányításnak kell
következnie egy GET
akcióra.)
A flashMessage
metódus 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 egyszerűen átadni a sablonnak és megjeleníteni. Ezért van ez a metódus, amely
elmenti ezt az üzenetet, és elérhetővé teszi a következő oldalbetöltéskor. A Flash üzenetek a fő sablonban, az
app/Presentation/@layout.latte
-ban jelennek meg, és így néznek ki:
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Ahogy már tudjuk, a flash üzenetek automatikusan átadódnak a sablonnak, így nem kell sokat gondolkodnunk rajta, egyszerűen működik. További információkért látogassa meg a dokumentációt.
Kommentek megjelenítése
Ez az egyik olyan dolog, amit egyszerűen imádni fog. A Nette Database nagyszerű funkcióval rendelkezik, amelyet Explorer-nek hívnak. Emlékszik még, hogy az adatbázis tábláit szándékosan InnoDB tárolóval hoztuk létre? Az Adminer így létrehozott valamit, amit idegen kulcsok-nak neveznek, amelyek sok munkát takarítanak meg nekünk.
A Nette Database Explorer idegen kulcsokat használ a táblák közötti kapcsolatok feloldására, és ezen kapcsolatok ismeretében automatikusan képes adatbázis lekérdezéseket létrehozni.
Ahogy biztosan emlékszik, a sablonnak átadtuk a $post
változót a PostPresenter::renderShow()
metódussal, és most iterálni szeretnénk az összes kommenten, amelyek post_id
oszlopának értéke megegyezik a
$post->id
-val. Ezt a $post->related('comments')
hívásával érhetjük el. Igen, ilyen
egyszerűen. Nézzük meg az eredményül 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>Kommentek</h2>
<div class="comments">
{foreach $comments as $comment}
<p><b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">
{$comment->name}
</a></b> írta:</p>
<div>{$comment->content}</div>
{/foreach}
</div>
...
Figyelje meg a speciális n:tag-if
attribútumot. Már tudja, hogyan működnek az n:atributy
. Ha az
attribútumhoz tag-
előtagot csatol, a funkcionalitás csak a HTML tagre vonatkozik, nem a tartalmára. Ez
lehetővé teszi számunkra, hogy a kommentelő nevét csak akkor tegyük linkké, ha megadta az e-mail címét. Ez a két sor
azonos:
<strong n:tag-if="$important"> Jó napot! </strong>
{if $important}<strong>{/if} Jó napot! {if $important}</strong>{/if}