Μοντέλο Component
Ένας σημαντικός όρος στο Nette είναι το component. Στις σελίδες
εισάγουμε οπτικά διαδραστικά components,
τα components είναι επίσης φόρμες ή όλα τα στοιχεία τους. Οι δύο βασικές
κλάσεις από τις οποίες κληρονομούν όλα αυτά τα components αποτελούν μέρος
του πακέτου nette/component-model
και έχουν ως αποστολή τη δημιουργία
μιας ιεραρχικής δενδροειδούς δομής components.
Component
Η Nette\ComponentModel\Component
είναι ο κοινός πρόγονος όλων των components. Περιέχει τις μεθόδους
getName()
που επιστρέφει το όνομα του component και τη μέθοδο
getParent()
που επιστρέφει τον γονέα του. Και τα δύο μπορούν να
οριστούν με τη μέθοδο setParent()
– η πρώτη παράμετρος είναι ο
γονέας και η δεύτερη το όνομα του component.
lookup (string $type): ?Component
Αναζητά στην ιεραρχία προς τα πάνω ένα αντικείμενο της ζητούμενης
κλάσης ή interface. Για παράδειγμα, το
$component->lookup(Nette\Application\UI\Presenter::class)
επιστρέφει τον presenter, εάν το
component είναι συνδεδεμένο με αυτόν, ακόμη και μέσω πολλών επιπέδων.
lookupPath (string $type): ?string
Επιστρέφει τη λεγόμενη διαδρομή, η οποία είναι μια συμβολοσειρά που
δημιουργείται από τη συνένωση των ονομάτων όλων των components στη διαδρομή
μεταξύ του τρέχοντος και του αναζητούμενου component. Έτσι, π.χ., το
$component->lookupPath(Nette\Application\UI\Presenter::class)
επιστρέφει ένα μοναδικό
αναγνωριστικό του component σε σχέση με τον presenter.
Container
Η Nette\ComponentModel\Container
είναι το γονικό component, δηλ. ένα component που περιέχει απογόνους και
σχηματίζει έτσι μια δενδροειδή δομή. Διαθέτει μεθόδους για εύκολη
προσθήκη, ανάκτηση και αφαίρεση αντικειμένων. Είναι ο πρόγονος, για
παράδειγμα, της φόρμας ή των κλάσεων Control
και Presenter
.
getComponent (string $name): ?Component
Επιστρέφει το component. Κατά την προσπάθεια ανάκτησης ενός μη ορισμένου
απογόνου, καλείται το factory createComponent($name)
. Η μέθοδος
createComponent($name)
καλεί στο τρέχον component τη μέθοδο
createComponent<όνομα_component>
και της περνά ως παράμετρο το όνομα του
component. Το δημιουργημένο component προστίθεται στη συνέχεια στο τρέχον component
ως απόγονός του. Αυτές οι μέθοδοι ονομάζονται factories component και μπορούν να
υλοποιηθούν από απογόνους της κλάσης Container
.
getComponents(): array
Επιστρέφει τους άμεσους απογόνους ως πίνακα. Τα κλειδιά περιέχουν τα ονόματα αυτών των components. Σημείωση: στην έκδοση 3.0.x η μέθοδος επέστρεφε έναν iterator αντί για πίνακα και η πρώτη της παράμετρος καθόριζε αν τα components έπρεπε να διασχιστούν σε βάθος, και η δεύτερη αντιπροσώπευε ένα φίλτρο τύπου. Αυτές οι παράμετροι είναι deprecated.
getComponentTree(): array
Ανακτά ολόκληρη την ιεραρχία των components, συμπεριλαμβανομένων όλων των ενσωματωμένων θυγατρικών components, ως ευρετηριασμένο πίνακα. Η αναζήτηση γίνεται πρώτα σε βάθος.
Παρακολούθηση προγόνων
Το μοντέλο component του Nette επιτρέπει πολύ δυναμική εργασία με το δέντρο (μπορούμε να αφαιρούμε, να μετακινούμε, να προσθέτουμε components), επομένως θα ήταν λάθος να βασιζόμαστε στο γεγονός ότι μετά τη δημιουργία ενός component είναι αμέσως γνωστός ο γονέας, ο γονέας του γονέα κ.λπ. (στον κατασκευαστή). Τις περισσότερες φορές, ο γονέας δεν είναι καθόλου γνωστός κατά τη δημιουργία.
Πώς να αναγνωρίσετε πότε ένα component συνδέθηκε στο δέντρο του presenter; Η
παρακολούθηση της αλλαγής του γονέα δεν αρκεί, γιατί μπορεί να έχει
συνδεθεί στον presenter ο γονέας του γονέα, για παράδειγμα. Η μέθοδος monitor($type, $attached,
$detached) βοηθάει. Κάθε component μπορεί να παρακολουθεί οποιονδήποτε αριθμό
κλάσεων και interfaces. Η σύνδεση ή η αποσύνδεση ανακοινώνεται με την κλήση
του callback $attached
ή $detached
αντίστοιχα, και την παράδοση του
αντικειμένου της παρακολουθούμενης κλάσης.
Για καλύτερη κατανόηση, ένα παράδειγμα: η κλάση UploadControl
, που
αντιπροσωπεύει ένα στοιχείο φόρμας για την αποστολή αρχείων στο Nette
Forms, πρέπει να ορίσει το attribute enctype
της φόρμας στην τιμή
multipart/form-data
. Κατά τη στιγμή της δημιουργίας του αντικειμένου,
όμως, μπορεί να μην είναι συνδεδεμένο με καμία φόρμα. Πότε λοιπόν
πρέπει να τροποποιηθεί η φόρμα; Η λύση είναι απλή – στον κατασκευαστή
ζητείται η παρακολούθηση:
class UploadControl extends Nette\Forms\Controls\BaseControl
{
public function __construct($label)
{
$this->monitor(Nette\Forms\Form::class, function ($form): void {
$form->setHtmlAttribute('enctype', 'multipart/form-data');
});
// ...
}
// ...
}
και μόλις η φόρμα είναι διαθέσιμη, καλείται το callback. (Παλαιότερα,
χρησιμοποιούνταν αντί αυτού η κοινή μέθοδος attached
ή
detached
).