Σελίδα με την ανάρτηση
Τώρα θα δημιουργήσουμε μια άλλη σελίδα του blog, η οποία θα εμφανίζει μια συγκεκριμένη ανάρτηση.
Πρέπει να δημιουργήσουμε μια νέα μέθοδο render, η οποία θα λαμβάνει ένα
συγκεκριμένο άρθρο και θα το περνά στο πρότυπο. Το να έχουμε αυτή τη
μέθοδο στον HomePresenter
δεν είναι πολύ ωραίο, επειδή μιλάμε για ένα
άρθρο και όχι για την αρχική σελίδα. Ας δημιουργήσουμε λοιπόν τον
PostPresenter
στο app/Presentation/Post/
. Αυτός ο presenter χρειάζεται επίσης
να συνδεθεί στη βάση δεδομένων, οπότε θα γράψουμε ξανά έναν
κατασκευαστή που θα απαιτεί σύνδεση στη βάση δεδομένων.
Ο PostPresenter
θα μπορούσε λοιπόν να μοιάζει έτσι:
<?php
namespace App\Presentation\Post;
use Nette;
use Nette\Application\UI\Form;
final class PostPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function renderShow(int $id): void
{
$this->template->post = $this->database
->table('posts')
->get($id);
}
}
Δεν πρέπει να ξεχάσουμε να αναφέρουμε το σωστό namespace
App\Presentation\Post
, το οποίο υπόκειται στη ρύθμιση αντιστοίχισης
presenter.
Η μέθοδος renderShow
απαιτεί ένα όρισμα – το ID ενός συγκεκριμένου
άρθρου που πρέπει να εμφανιστεί. Στη συνέχεια, φορτώνει αυτό το άρθρο
από τη βάση δεδομένων και το περνά στο πρότυπο.
Στο πρότυπο Home/default.latte
θα εισαγάγουμε έναν σύνδεσμο προς την
action Post:show
.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Το tag {link}
δημιουργεί μια διεύθυνση URL που οδηγεί στην action
Post:show
. Επίσης, περνά το ID της ανάρτησης ως όρισμα.
Το ίδιο μπορούμε να γράψουμε συντομευμένα χρησιμοποιώντας την n:ιδιότητα:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Η ιδιότητα n:href
είναι ανάλογη του tag {link}
.
Για την action Post:show
όμως, δεν υπάρχει ακόμα πρότυπο. Μπορούμε να
δοκιμάσουμε να ανοίξουμε τον σύνδεσμο προς αυτήν την ανάρτηση. Η Tracy θα εμφανίσει ένα σφάλμα, επειδή το πρότυπο
Post/show.latte
δεν υπάρχει ακόμα. Εάν βλέπετε διαφορετικό μήνυμα
σφάλματος, τότε πιθανότατα θα πρέπει να ενεργοποιήσετε το
mod_rewrite
στον webserver.
Θα δημιουργήσουμε λοιπόν το πρότυπο Post/show.latte
με το ακόλουθο
περιεχόμενο:
{block content}
<p><a n:href="Home:default">← πίσω στη λίστα αναρτήσεων</a></p>
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h1 n:block="title">{$post->title}</h1>
<div class="post">{$post->content}</div>
Τώρα ας περάσουμε από τα επιμέρους μέρη του προτύπου.
Η πρώτη γραμμή ξεκινά τον ορισμό του μπλοκ με το όνομα “content” όπως
ακριβώς και στην αρχική σελίδα. Αυτό το μπλοκ θα εμφανιστεί ξανά στο
κύριο πρότυπο. Όπως βλέπετε, λείπει το τελικό tag {/block}
. Αυτό είναι
προαιρετικό.
Στην επόμενη γραμμή υπάρχει ένας σύνδεσμος πίσω στη λίστα των άρθρων
του blog, ώστε ο χρήστης να μπορεί εύκολα να κινείται μεταξύ της λίστας
των άρθρων και ενός συγκεκριμένου. Επειδή χρησιμοποιούμε την ιδιότητα
n:href
, το Nette φροντίζει αυτόματα για τη δημιουργία των συνδέσμων. Ο
σύνδεσμος οδηγεί στην action default
του presenter Home
(μπορούμε να
γράψουμε επίσης n:href="Home:"
, επειδή η action με το όνομα default
μπορεί να παραλειφθεί, συμπληρώνεται αυτόματα).
Η τρίτη γραμμή μορφοποιεί την εμφάνιση της ημερομηνίας χρησιμοποιώντας το φίλτρο που ήδη γνωρίζουμε.
Η τέταρτη γραμμή εμφανίζει τον τίτλο του blog στο HTML tag <h1>
.
Αυτό το tag περιέχει μια ιδιότητα που ίσως δεν γνωρίζετε
(n:block="title"
). Μπορείτε να μαντέψετε τι κάνει; Αν διαβάσατε
προσεκτικά το προηγούμενο μέρος, τότε ήδη ξέρετε ότι πρόκειται για μια
n:ιδιότητα
. Αυτό είναι ένα άλλο παράδειγμά τους, το οποίο είναι
ισοδύναμο με:
{block title}<h1>{$post->title}</h1>{/block}
Με απλά λόγια, αυτό το μπλοκ επαναπροσδιορίζει το μπλοκ με το όνομα
title
. Αυτό το μπλοκ είναι ήδη ορισμένο στο κύριο layout πρότυπο
(/app/Presentation/@layout.latte:11
) και όπως και με την επικάλυψη μεθόδων στην
OOP, ακριβώς το ίδιο αυτό το μπλοκ στο κύριο πρότυπο επικαλύπτεται. Έτσι,
το <title>
της σελίδας τώρα περιέχει τον τίτλο της
εμφανιζόμενης ανάρτησης και μας αρκούσε γι' αυτό να χρησιμοποιήσουμε
μόνο μια απλή ιδιότητα n:block="title"
. Υπέροχο, έτσι δεν είναι;
Η πέμπτη και τελευταία γραμμή του προτύπου εμφανίζει ολόκληρο το περιεχόμενο μιας συγκεκριμένης ανάρτησης.
Έλεγχος του ID της ανάρτησης
Τι θα συμβεί αν κάποιος αλλάξει το ID στη διεύθυνση URL και εισαγάγει
κάποιο ανύπαρκτο id
; Θα έπρεπε να προσφέρουμε στον χρήστη ένα
ωραίο σφάλμα τύπου “η σελίδα δεν βρέθηκε”. Θα τροποποιήσουμε λοιπόν
λίγο τη μέθοδο render στον PostPresenter
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Η σελίδα δεν βρέθηκε');
}
$this->template->post = $post;
}
Εάν η ανάρτηση δεν μπορεί να βρεθεί, καλώντας το $this->error(...)
θα
εμφανίσουμε μια σελίδα σφάλματος 404 με ένα κατανοητό μήνυμα. Προσοχή
στο ότι σε κατάσταση ανάπτυξης (localhost) δεν θα δείτε αυτήν τη σελίδα
σφάλματος. Αντ' αυτού, θα εμφανιστεί η Tracy με λεπτομέρειες για την
εξαίρεση, κάτι που είναι αρκετά βολικό για την ανάπτυξη. Αν θέλουμε να
εμφανίζονται και οι δύο καταστάσεις, αρκεί απλώς να αλλάξουμε το
όρισμα της μεθόδου setDebugMode
στο αρχείο Bootstrap.php
.
Σύνοψη
Έχουμε μια βάση δεδομένων με αναρτήσεις και μια web εφαρμογή που έχει δύο views – η πρώτη εμφανίζει μια επισκόπηση όλων των αναρτήσεων και η δεύτερη εμφανίζει μια συγκεκριμένη ανάρτηση.