Kommentare
Der Blog wurde eingerichtet, wir haben einige sehr gute Blogbeiträge geschrieben und sie über Adminer veröffentlicht. Die Leute lesen den Blog und sind sehr begeistert von unseren Ideen. Wir erhalten jeden Tag viele E-Mails mit Lob. Aber was nützt all das Lob, wenn wir es nur in der E-Mail bekommen, so dass niemand sonst es lesen kann? Wäre es nicht besser, wenn die Leute direkt im Blog kommentieren könnten, damit alle anderen lesen können, wie toll wir sind?
Lasst uns alle Artikel kommentierbar machen.
Eine neue Tabelle erstellen
Starten Sie Adminer erneut und erstellen Sie eine neue Tabelle mit dem Namen comments
mit diesen Spalten:
id
int, Prüfung auf Autoinkrement (AI)post_id
, ein Fremdschlüssel, der auf die Tabelleposts
verweistname
varchar, Länge 255email
varchar, Länge 255content
textcreated_at
Zeitstempel
Es sollte wie folgt aussehen:
Vergessen Sie nicht, die InnoDB-Tabellenspeicherung zu verwenden und klicken Sie auf Speichern.
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;
Formular für Kommentare
Zuerst müssen wir ein Formular erstellen, das es den Benutzern ermöglicht, auf unserer Seite zu kommentieren. Nette Framework hat eine großartige Unterstützung für Formulare. Sie können in einem Presenter konfiguriert und in einer Vorlage gerendert werden.
Nette Framework hat ein Konzept von Komponenten. Eine Komponente ist eine wiederverwendbare Klasse oder ein
Stück Code, das mit einer anderen Komponente verbunden werden kann. Auch ein Präsentator ist eine Komponente. Jede Komponente
wird mit Hilfe der Komponentenfabrik erstellt. Definieren wir also die Kommentarformularfabrik in PostPresenter
.
protected function createComponentCommentForm(): Form
{
$form = new Form; // bedeutet Nette\Application\UI\Form
$form->addText('name', 'Ihr Name:')
->setRequired();
$form->addEmail('email', 'Email:');
$form->addTextArea('content', 'Kommentar:')
->setRequired();
$form->addSubmit('send', 'Kommentar veröffentlichen');
return $form;
}
Erklären wir sie ein wenig. Die erste Zeile erzeugt eine neue Instanz der Komponente Form
. Die folgenden Methoden
fügen HTML-Eingaben in die Formulardefinition ein. ->addText
wird als
<input type=text name=name>
mit <label>Your name:</label>
. Wie Sie vielleicht schon
erraten haben, fügt die ->addTextArea
ein <textarea>
und ->addSubmit
fügt ein
<input type=submit>
. Es gibt noch weitere Methoden dieser Art, aber das ist alles, was Sie im Moment wissen
müssen. Sie können mehr in der Dokumentation erfahren.
Sobald die Formularkomponente in einem Presenter definiert ist, können wir sie in einer Vorlage rendern (anzeigen). Dazu
platzieren Sie das Tag {control}
am Ende der Post-Detail-Vorlage in Post/show.latte
. Da der Name der
Komponente commentForm
ist (er leitet sich vom Namen der Methode createComponentCommentForm
ab), sieht
das Tag wie folgt aus
...
<h2>Post new comment</h2>
{control commentForm}
Wenn Sie sich nun die Details eines Beitrags ansehen, wird ein neues Formular für die Eingabe von Kommentaren angezeigt.
Speichern in der Datenbank
Haben Sie versucht, einige Daten zu übermitteln? Vielleicht haben Sie bemerkt, dass das Formular keine Aktion ausführt. Es ist einfach da, sieht cool aus und tut nichts. Wir müssen eine Callback-Methode anhängen, die die übermittelten Daten speichert.
Fügen Sie die folgende Zeile vor der Zeile return
in der Komponentenfabrik für
commentForm
ein:
$form->onSuccess[] = $this->commentFormSucceeded(...);
Sie bedeutet „nachdem das Formular erfolgreich abgeschickt wurde, rufe die Methode commentFormSucceeded
des
aktuellen Präsentators auf“. Diese Methode existiert noch nicht, also erstellen wir sie.
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');
}
Sie sollten sie direkt nach der Komponentenfabrik commentForm
platzieren.
Die neue Methode hat ein Argument, nämlich die Instanz des übermittelten Formulars, die von der Komponentenfabrik erstellt
wurde. Wir erhalten die übermittelten Werte in $data
. Und dann fügen wir die Daten in die Datenbanktabelle
comments
ein.
Es gibt noch zwei weitere Methodenaufrufe zu erklären. Der Redirect leitet buchstäblich zur aktuellen Seite um. Das sollten
Sie jedes Mal tun, wenn das Formular übermittelt wurde, gültig ist und die Callback-Operation das getan hat, was sie hätte tun
sollen. Wenn Sie die Seite nach dem Absenden des Formulars umleiten, wird auch nicht die bekannte Meldung
Would you like to submit the post data again?
angezeigt, die Sie manchmal im Browser sehen können. (Im Allgemeinen
sollten Sie den Benutzer nach dem Absenden eines Formulars mit der Methode POST
immer zu einer Aktion
GET
weiterleiten).
Die flashMessage
dient dazu, den Benutzer über das Ergebnis einer bestimmten Operation zu informieren. Da wir
eine Routing vornehmen, kann die Nachricht nicht direkt an die Vorlage übergeben und gerendert werden. Deshalb gibt es diese
Methode, die sie speichert und beim nächsten Laden der Seite zur Verfügung stellt. Die Flash-Nachrichten werden in der
Standarddatei app/UI/@layout.latte
gerendert und sehen wie folgt aus:
<div n:foreach="$flashes as $flash" n:class="flash, $flash->type">
{$flash->message}
</div>
Wie wir bereits wissen, werden sie automatisch an die Vorlage übergeben, so dass Sie nicht viel darüber nachdenken müssen, es funktioniert einfach. Für weitere Details siehe die Dokumentation.
Rendering der Kommentare
Dies ist eines der Dinge, die Sie einfach lieben werden. Nette Database hat diese coole Funktion namens Explorer. Erinnern Sie sich, dass wir die Tabellen als InnoDB erstellt haben? Adminer hat die sogenannten Fremdschlüssel erstellt, die uns eine Menge Arbeit ersparen werden.
Der Nette Database Explorer verwendet die Fremdschlüssel, um die Beziehungen zwischen den Tabellen aufzulösen, und da er die Beziehungen kennt, kann er automatisch Abfragen für Sie erstellen.
Wie Sie sich vielleicht erinnern, haben wir die Variable $post
an die Vorlage in
PostPresenter::renderShow()
übergeben, und jetzt wollen wir alle Kommentare durchgehen, deren Spalte
post_id
gleich unserer $post->id
ist. Sie können dies tun, indem Sie
$post->related('comments')
aufrufen. So einfach ist das. Sehen Sie sich den resultierenden Code an.
public function renderShow(int $id): void
{
...
$this->template->post = $post;
$this->template->comments = $post->related('comments')->order('created_at');
}
Und die Vorlage:
...
<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>
...
Beachten Sie das spezielle Attribut n:tag-if
. Sie wissen bereits, wie n: attributes
funktioniert.
Wenn Sie dem Attribut tag-
vorangestellt haben, umschließt es nur die Tags, nicht deren Inhalt. So können Sie den
Namen des Kommentators in einen Link umwandeln, wenn er seine E-Mail-Adresse angegeben hat. Diese beiden Zeilen sind im Ergebnis
identisch:
<strong n:tag-if="$important"> Hello there! </strong>
{if $important}<strong>{/if} Hello there! {if $important}</strong>{/if}