Σελίδα με την ανάρτηση
Τώρα θα δημιουργήσουμε μια άλλη σελίδα του blog, η οποία θα εμφανίζει μια συγκεκριμένη ανάρτηση.
Πρέπει να δημιουργήσουμε μια νέα μέθοδο render, η οποία θα λαμβάνει ένα
συγκεκριμένο άρθρο και θα το περνά στο template. Το να έχουμε αυτή τη μέθοδο
στον HomePresenter
δεν είναι πολύ ωραίο, επειδή μιλάμε για ένα άρθρο
και όχι για την αρχική σελίδα. Ας δημιουργήσουμε λοιπόν τον
PostPresenter
στο app/Presentation/Post/
. Αυτός ο presenter χρειάζεται επίσης
να συνδεθεί στη βάση δεδομένων, οπότε θα γράψουμε ξανά έναν constructor που
θα απαιτεί σύνδεση στη βάση δεδομένων.
Ο 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 ενός συγκεκριμένου
άρθρου που πρέπει να εμφανιστεί. Στη συνέχεια, φορτώνει αυτό το άρθρο
από τη βάση δεδομένων και το περνά στο template.
Στο template 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:attribute:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Το attribute n:href
είναι ανάλογο του tag {link}
.
Για την action Post:show
όμως, δεν υπάρχει ακόμα template. Μπορούμε να
δοκιμάσουμε να ανοίξουμε τον σύνδεσμο προς αυτήν την ανάρτηση. Η Tracy θα εμφανίσει ένα σφάλμα, επειδή το template
Post/show.latte
δεν υπάρχει ακόμα. Εάν βλέπετε διαφορετικό μήνυμα
σφάλματος, τότε πιθανότατα θα πρέπει να ενεργοποιήσετε το
mod_rewrite
στον webserver.
Θα δημιουργήσουμε λοιπόν το template 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>
Τώρα ας περάσουμε από τα επιμέρους μέρη του template.
Η πρώτη γραμμή ξεκινά τον ορισμό του μπλοκ με το όνομα “content” όπως
ακριβώς και στην αρχική σελίδα. Αυτό το μπλοκ θα εμφανιστεί ξανά στο
κύριο template. Όπως βλέπετε, λείπει το τελικό tag {/block}
. Αυτό είναι
προαιρετικό.
Στην επόμενη γραμμή υπάρχει ένας σύνδεσμος πίσω στη λίστα των άρθρων
του blog, ώστε ο χρήστης να μπορεί εύκολα να κινείται μεταξύ της λίστας
των άρθρων και ενός συγκεκριμένου. Επειδή χρησιμοποιούμε το attribute
n:href
, το Nette φροντίζει αυτόματα για τη δημιουργία των συνδέσμων. Ο
σύνδεσμος οδηγεί στην action default
του presenter Home
(μπορούμε να
γράψουμε επίσης n:href="Home:"
, επειδή η action με το όνομα default
μπορεί να παραλειφθεί, συμπληρώνεται αυτόματα).
Η τρίτη γραμμή μορφοποιεί την εμφάνιση της ημερομηνίας χρησιμοποιώντας το φίλτρο που ήδη γνωρίζουμε.
Η τέταρτη γραμμή εμφανίζει τον τίτλο του blog στο HTML tag <h1>
.
Αυτό το tag περιέχει ένα attribute που ίσως δεν γνωρίζετε (n:block="title"
).
Μπορείτε να μαντέψετε τι κάνει; Αν διαβάσατε προσεκτικά το προηγούμενο
μέρος, τότε ήδη ξέρετε ότι πρόκειται για ένα n:attribute
. Αυτό είναι
ένα άλλο παράδειγμά τους, το οποίο είναι ισοδύναμο με:
{block title}<h1>{$post->title}</h1>{/block}
Με απλά λόγια, αυτό το μπλοκ επαναπροσδιορίζει το μπλοκ με το όνομα
title
. Αυτό το μπλοκ είναι ήδη ορισμένο στο κύριο layout template
(/app/Presentation/@layout.latte:11
) και όπως και με την επικάλυψη μεθόδων στην
OOP, ακριβώς το ίδιο αυτό το μπλοκ στο κύριο template επικαλύπτεται. Έτσι, το
<title>
της σελίδας τώρα περιέχει τον τίτλο της εμφανιζόμενης
ανάρτησης και μας αρκούσε γι' αυτό να χρησιμοποιήσουμε μόνο ένα απλό
attribute n:block="title"
. Υπέροχο, έτσι δεν είναι;
Η πέμπτη και τελευταία γραμμή του template εμφανίζει ολόκληρο το περιεχόμενο μιας συγκεκριμένης ανάρτησης.
Έλεγχος του 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 – η πρώτη εμφανίζει μια επισκόπηση όλων των αναρτήσεων και η δεύτερη εμφανίζει μια συγκεκριμένη ανάρτηση.