Αρχική σελίδα του blog
Τώρα θα δημιουργήσουμε την αρχική σελίδα που θα εμφανίζει τις τελευταίες αναρτήσεις.
Πριν ξεκινήσουμε, είναι απαραίτητο να γνωρίζουμε τουλάχιστον τα βασικά του σχεδιαστικού προτύπου Model-View-Presenter (παρόμοιο με το MVC):
- Model – το επίπεδο που εργάζεται με τα δεδομένα. Είναι εντελώς διαχωρισμένο από την υπόλοιπη εφαρμογή. Επικοινωνεί μόνο με τον presenter.
- View – το επίπεδο front-end. Αποδίδει τα ζητούμενα δεδομένα χρησιμοποιώντας templates και τα εμφανίζει στον χρήστη.
- Presenter (ή Controller) – το συνδετικό επίπεδο. Ο Presenter συνδέει το Model και το View. Επεξεργάζεται τα requests, ζητά δεδομένα από το Model και τα επιστρέφει στο View.
Στην περίπτωση απλών εφαρμογών, όπως θα είναι το blog μας, ολόκληρο το επίπεδο model θα αποτελείται μόνο από ερωτήματα στη βάση δεδομένων – γι' αυτό δεν χρειαζόμαστε προς το παρόν επιπλέον κώδικα. Για αρχή, θα δημιουργήσουμε λοιπόν μόνο τους presenters και τα templates. Στο Nette, κάθε presenter έχει τα δικά του templates, οπότε θα τα δημιουργούμε ταυτόχρονα.
Δημιουργία βάσης δεδομένων με το Adminer
Για την αποθήκευση δεδομένων θα χρησιμοποιήσουμε τη βάση δεδομένων MySQL, επειδή είναι η πιο διαδεδομένη μεταξύ των προγραμματιστών web εφαρμογών. Ωστόσο, αν δεν θέλετε να τη χρησιμοποιήσετε, μπορείτε να επιλέξετε μια βάση δεδομένων της αρεσκείας σας.
Τώρα θα προετοιμάσουμε τη δομή της βάσης δεδομένων όπου θα αποθηκεύονται τα άρθρα του blog μας. Θα ξεκινήσουμε πολύ απλά – θα δημιουργήσουμε μόνο έναν πίνακα για τις αναρτήσεις.
Για τη δημιουργία της βάσης δεδομένων μπορούμε να κατεβάσουμε το Adminer, ή άλλο αγαπημένο σας εργαλείο διαχείρισης βάσεων δεδομένων.
Ανοίγουμε το Adminer και δημιουργούμε μια νέα βάση δεδομένων με το όνομα
quickstart
.
Δημιουργούμε έναν νέο πίνακα με το όνομα posts
και με τις
ακόλουθες στήλες:
id
int, επιλέγουμε autoincrement (AI)title
varchar, length 255content
textcreated_at
timestamp
Η τελική δομή θα πρέπει να μοιάζει έτσι:

CREATE TABLE `posts` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`title` varchar(255) NOT NULL,
`content` text NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;
Είναι πραγματικά σημαντικό να χρησιμοποιήσετε την αποθήκευση InnoDB. Σε λίγο θα δείξουμε γιατί. Προς το παρόν, απλά επιλέξτε την και κάντε κλικ στην αποθήκευση.
Πριν δημιουργήσουμε τη δυνατότητα προσθήκης άρθρων στη βάση δεδομένων μέσω της εφαρμογής, προσθέστε μερικά δείγματα άρθρων στο blog χειροκίνητα.
INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1, 'Article One', 'Lorem ipusm dolor one', CURRENT_TIMESTAMP),
(2, 'Article Two', 'Lorem ipsum dolor two', CURRENT_TIMESTAMP),
(3, 'Article Three', 'Lorem ipsum dolor three', CURRENT_TIMESTAMP);
Σύνδεση στη βάση δεδομένων
Τώρα που η βάση δεδομένων έχει δημιουργηθεί και έχουμε αποθηκεύσει μερικά άρθρα σε αυτήν, είναι η κατάλληλη στιγμή να τα εμφανίσουμε στην όμορφη νέα μας σελίδα.
Πρώτα πρέπει να πούμε στην εφαρμογή ποια βάση δεδομένων να
χρησιμοποιήσει. Η σύνδεση στη βάση δεδομένων ρυθμίζεται στο αρχείο
config/common.neon
χρησιμοποιώντας το DSN και
τα διαπιστευτήρια σύνδεσης. Θα πρέπει να μοιάζει κάπως έτσι:
database:
dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
user: *εισάγετε εδώ το όνομα χρήστη*
password: *εισάγετε εδώ τον κωδικό πρόσβασης στη βάση δεδομένων*
Κατά την επεξεργασία αυτού του αρχείου, προσέξτε την εσοχή των γραμμών. Η μορφή NEON δέχεται τόσο εσοχή με κενά όσο και εσοχή με tabs, αλλά όχι και τα δύο ταυτόχρονα. Το προεπιλεγμένο αρχείο διαμόρφωσης στο Web Project χρησιμοποιεί tabs.
Πέρασμα της σύνδεσης βάσης δεδομένων
Ο presenter HomePresenter
, ο οποίος θα είναι υπεύθυνος για την εμφάνιση
των άρθρων, χρειάζεται σύνδεση στη βάση δεδομένων. Για να την
αποκτήσουμε, θα χρησιμοποιήσουμε τον constructor, ο οποίος θα
μοιάζει έτσι:
<?php
namespace App\Presentation\Home;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
// ...
}
Φόρτωση αναρτήσεων από τη βάση δεδομένων
Τώρα θα φορτώσουμε τις αναρτήσεις από τη βάση δεδομένων και θα τις στείλουμε στο template, το οποίο στη συνέχεια θα τις αποδώσει ως κώδικα HTML. Γι' αυτό προορίζεται η λεγόμενη render μέθοδος:
public function renderDefault(): void
{
$this->template->posts = $this->database
->table('posts')
->order('created_at DESC')
->limit(5);
}
Ο presenter τώρα περιέχει μία μέθοδο απόδοσης renderDefault()
, η οποία
περνά δεδομένα από τη βάση δεδομένων στο template (View). Τα templates βρίσκονται
στο app/Presentation/{PresenterName}/{viewName}.latte
, οπότε σε αυτήν την περίπτωση το
template βρίσκεται στο app/Presentation/Home/default.latte
. Στο template τώρα θα είναι
διαθέσιμη η μεταβλητή $posts
, στην οποία βρίσκονται οι αναρτήσεις
που λήφθηκαν από τη βάση δεδομένων.
Template
Για ολόκληρη την ιστοσελίδα έχουμε διαθέσιμο το κύριο template (το οποίο ονομάζεται layout, περιέχει την κεφαλίδα, τα στυλ, το υποσέλιδο,…) και επιπλέον συγκεκριμένα templates για κάθε view (π.χ. για την εμφάνιση των αναρτήσεων στο blog), τα οποία μπορούν να αντικαταστήσουν ορισμένα μέρη του κύριου template.
Στην προεπιλεγμένη κατάσταση, το layout template βρίσκεται στο
app/Presentation/@layout.latte
και περιέχει:
...
{include content}
...
Η σύνταξη {include content}
εισάγει στο κύριο template ένα μπλοκ με το
όνομα content
. Αυτό θα το ορίσουμε στα templates των επιμέρους views. Στην
περίπτωσή μας, το αρχείο Home/default.latte
θα το τροποποιήσουμε
ως εξής:
{block content}
Hello World
{/block}
Με αυτόν τον τρόπο ορίσαμε το μπλοκ
content, το οποίο θα εισαχθεί στο κύριο layout. Αν ανανεώσουμε ξανά τον
browser, θα δούμε τη σελίδα με το κείμενο “Hello World” (στον πηγαίο κώδικα και
με την HTML κεφαλίδα και υποσέλιδο που ορίζονται στο @layout.latte
).
Ας εμφανίσουμε τις αναρτήσεις από το blog – θα τροποποιήσουμε το template ως εξής:
{block content}
<h1>Το blog μου</h1>
{foreach $posts as $post}
<div class="post">
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h2>{$post->title}</h2>
<div>{$post->content|truncate:256}</div>
</div>
{/foreach}
{/block}
Αν ανανεώσουμε τον browser, θα δούμε τη λίστα όλων των αναρτήσεων. Η λίστα
δεν είναι ακόμα πολύ όμορφη, ούτε πολύχρωμη, γι' αυτό μπορούμε να
προσθέσουμε στο αρχείο www/css/style.css
μερικά στυλ CSS και να το
συνδέσουμε στο layout:
...
<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
Το tag {foreach}
επαναλαμβάνει όλες τις αναρτήσεις που περάσαμε στο
template στη μεταβλητή $posts
, και για κάθε μία αποδίδει το δεδομένο
κομμάτι HTML. Συμπεριφέρεται ακριβώς όπως ο κώδικας PHP.
Τη σύνταξη |date:
την ονομάζουμε φίλτρο. Τα φίλτρα προορίζονται
για τη μορφοποίηση της εξόδου. Αυτό το συγκεκριμένο φίλτρο μετατρέπει
την ημερομηνία (π.χ. 2013-04-12
) στην πιο ευανάγνωστη μορφή της
(April 12, 2013
). Το φίλτρο |truncate
περικόπτει τη συμβολοσειρά στο
αναφερόμενο μέγιστο μήκος και στην περίπτωση που η συμβολοσειρά
περικοπεί, προσθέτει στο τέλος τρεις τελείες. Δεδομένου ότι πρόκειται
για προεπισκόπηση, δεν έχει νόημα να εμφανίζεται ολόκληρο το
περιεχόμενο του άρθρου. Άλλα προεπιλεγμένα φίλτρα βρίσκουμε στην τεκμηρίωση ή μπορούμε να
δημιουργήσουμε τα δικά μας, όταν χρειάζεται.
Ακόμα ένα πράγμα. Τον προηγούμενο κώδικα μπορούμε να τον συντομεύσουμε και να τον απλοποιήσουμε. Αυτό το πετυχαίνουμε αντικαθιστώντας τα Latte tags με n:attributes:
{block content}
<h1>Το blog μου</h1>
<div n:foreach="$posts as $post" class="post">
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h2>{$post->title}</h2>
<div>{$post->content|truncate:256}</div>
</div>
{/block}
Το attribute n:foreach
περιβάλλει το div με ένα μπλοκ foreach
(λειτουργεί ακριβώς το ίδιο με τον προηγούμενο κώδικα).
Σύνοψη
Τώρα έχουμε μια πολύ απλή βάση δεδομένων MySQL με μερικές αναρτήσεις. Η εφαρμογή συνδέεται σε αυτήν τη βάση δεδομένων και εμφανίζει μια απλή λίστα αυτών των αναρτήσεων στο template.