Komentarji
Blog je bil uveden, napisali smo nekaj zelo dobrih blogov in jih objavili prek Adminerja. Ljudje berejo blog in so zelo navdušeni nad našimi idejami. Vsak dan prejmemo veliko elektronskih sporočil s pohvalami. Toda čemu so vse te pohvale, če jih dobimo samo v elektronski pošti, tako da jih nihče drug ne more prebrati? Ali ne bi bilo bolje, če bi ljudje lahko komentirali neposredno na blogu, tako da bi vsi drugi lahko prebrali, kako super smo?
Naj bo mogoče komentirati vse članke.
Ustvarjanje nove tabele
Ponovno zaženite program Adminer in ustvarite novo tabelo z imenom comments
s temi stolpci:
id
int, preverite samodejni prirastek (AI)post_id
, tuj ključ, ki se sklicuje na tabeloposts
name
varchar, dolžina 255email
varchar, dolžina 255content
besedilocreated_at
časovni žig
Izgledati mora takole:
Ne pozabite uporabiti shranjevanja tabel InnoDB in pritisnite Shrani.
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;
Obrazec za komentiranje
Najprej moramo ustvariti obrazec, ki bo uporabnikom omogočal komentiranje na naši strani. Okvir Nette ima odlično podporo za obrazce. Lahko jih konfigurirate v predstavniku in prikažete v predlogi.
Nette Framework ima koncept komponent. Komponenta** je razred ali del kode, ki ga je mogoče ponovno uporabiti in ga je
mogoče priključiti na drugo komponento. Tudi predstavnik je komponenta. Vsaka komponenta je ustvarjena s pomočjo tovarne
komponent. Zato definirajmo tovarno obrazca za komentarje v PostPresenter
.
protected function createComponentCommentForm(): Form
{
$form = new Form; // pomeni Nette\Application\UI\Form
$form->addText('name', 'Your name:')
->setRequired();
$form->addEmail('email', 'Email:');
$form->addTextArea('content', 'Comment:')
->setRequired();
$form->addSubmit('send', 'Publish comment');
return $form;
}
Malo jo razložimo. Prva vrstica ustvari nov primerek komponente Form
. Naslednje metode pripenjajo vhode HTML
v definicijo obrazca. ->addText
se bo prikazal kot <input type=text name=name>
z
<label>Your name:</label>
. Kot ste morda že uganili zdaj, ->addTextArea
priklopi
<textarea>
in ->addSubmit
doda vnos <input type=submit>
. Podobnih metod je
še več, vendar je to vse, kar morate zdaj vedeti. Več lahko izveste v dokumentaciji.
Ko je komponenta obrazca opredeljena v predstavniku, jo lahko upodobimo (prikažemo) v predlogi. To storite tako, da
postavite oznako {control}
na konec predloge podrobnosti prispevka, v Post/show.latte
. Ker je ime
komponente commentForm
(izhaja iz imena metode createComponentCommentForm
), bo oznaka videti takole
...
<h2>Post new comment</h2>
{control commentForm}
Če si zdaj ogledate podrobnosti neke objave, bo na voljo nov obrazec za objavo komentarjev.
Shranjevanje v zbirko podatkov
Ste poskusili poslati nekaj podatkov? Morda ste opazili, da obrazec ne izvede nobene akcije. Samo tam je, je videti kul in ne naredi ničesar. Nanj moramo priključiti metodo povratnega klica, ki bo shranila poslane podatke.
Pred vrstico return
v tovarni komponente za commentForm
postavite naslednjo vrstico :
$form->onSuccess[] = $this->commentFormSucceeded(...);
Pomeni “po uspešni oddaji obrazca pokliči metodo commentFormSucceeded
trenutnega predstavnika”. Ta metoda
še ne obstaja, zato jo ustvarimo.
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');
}
Postaviti jo morate takoj za tovarno komponent commentForm
.
Nova metoda ima en argument, ki je primerek obrazca, ki se pošilja in ga je ustvarila tovarna komponent. Oddane vrednosti
prejmemo v $data
. Nato pa podatke vstavimo v tabelo podatkovne zbirke comments
.
Razložiti je treba še dva klica metod. Preusmeritev dobesedno preusmeri na trenutno stran. To morate storiti vsakič, ko je
obrazec oddan, veljaven in je operacija povratnega klica naredila, kar bi morala. Prav tako pri preusmeritvi strani po oddaji
obrazca ne boste videli znanega sporočila Would you like to submit the post data again?
, ki se včasih pojavi
v brskalniku. (Na splošno morate po oddaji obrazca z metodo POST
uporabnika vedno preusmeriti na dejanje
GET
.)
Sporočilo flashMessage
je namenjeno obveščanju uporabnika o rezultatu neke operacije. Ker gre za preusmeritev,
sporočila ni mogoče neposredno posredovati predlogi in ga izrisati. Zato je tu ta metoda, ki ga bo shranila in dala na voljo ob
naslednjem nalaganju strani. Sporočila flash so prikazana v privzeti datoteki app/UI/@layout.latte
in so videti
takole:
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Kot že vemo, se samodejno posredujejo predlogi, zato vam o tem ni treba preveč razmišljati, preprosto deluje. Za več podrobnosti si oglejte dokumentacijo.
Prikazovanje komentarjev
To je ena od stvari, ki vam bo preprosto všeč. Podatkovna zbirka Nette ima to kul funkcijo z imenom Raziskovalec. Se spomnite, da smo tabele ustvarili kot InnoDB? Adminer je ustvaril tako imenovane tuje ključe, ki nam bodo prihranili ogromno dela.
Nette Database Explorer uporablja tuje ključe za reševanje razmerij med tabelami, in ker pozna razmerja, lahko samodejno ustvari poizvedbe za vas.
Kot se morda spomnite, smo spremenljivko $post
posredovali predlogi v PostPresenter::renderShow()
,
zdaj pa želimo iterirati po vseh komentarjih, ki imajo stolpec post_id
enak našemu $post->id
. To
lahko storite tako, da pokličete $post->related('comments')
. Tako preprosto je. Oglejte si nastalo kodo.
public function renderShow(int $id): void
{
...
$this->template->post = $post;
$this->template->comments = $post->related('comments')->order('created_at');
}
In predlogo:
...
<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>
...
Opazite poseben atribut n:tag-if
. Že veste, kako deluje n: attributes
. Če atributu predpomnite
tag-
, bo ovijal le oznake, ne pa tudi njihove vsebine. Tako lahko ime komentatorja spremenite v povezavo, če je
navedel svoj elektronski naslov. Rezultati teh dveh vrstic so enaki:
<strong n:tag-if="$important"> Hello there! </strong>
{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}