Μοντέλο
Καθώς η εφαρμογή μας αναπτύσσεται, σύντομα διαπιστώνουμε ότι πρέπει να εκτελέσουμε παρόμοιες λειτουργίες της βάσης δεδομένων σε διάφορες τοποθεσίες και σε διάφορους παρουσιαστές, για παράδειγμα να αποκτήσουμε τα πιο πρόσφατα δημοσιευμένα άρθρα. Αν βελτιώσουμε την εφαρμογή μας προσθέτοντας μια σημαία στα άρθρα για να υποδεικνύει μια κατάσταση εργασίας σε εξέλιξη, πρέπει επίσης να περάσουμε από όλες τις τοποθεσίες της εφαρμογής μας και να προσθέσουμε μια ρήτρα where για να βεβαιωθούμε ότι επιλέγονται μόνο τα έτοιμα άρθρα.
Σε αυτό το σημείο, η άμεση εργασία με τη βάση δεδομένων καθίσταται ανεπαρκής και θα είναι πιο έξυπνο να βοηθήσουμε τον εαυτό μας με μια νέα συνάρτηση που επιστρέφει τα δημοσιευμένα άρθρα. Και όταν αργότερα προσθέσουμε μια άλλη ρήτρα (για παράδειγμα για να μην εμφανίζονται άρθρα με μελλοντική ημερομηνία), επεξεργαζόμαστε τον κώδικά μας μόνο σε ένα σημείο.
Θα τοποθετήσουμε τη συνάρτηση στην κλάση PostFacade
και θα την
ονομάσουμε getPublicArticles()
.
Θα δημιουργήσουμε την κλάση μοντέλου PostFacade
στον κατάλογο
app/Model/
για να αναλάβει τη φροντίδα των άρθρων μας:
<?php
namespace App\Model;
use Nette;
final class PostFacade
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function getPublicArticles()
{
return $this->database
->table('posts')
->where('created_at < ', new \DateTime)
->order('created_at DESC');
}
}
Στην κλάση περνάμε την βάση δεδομένων Explorer. Με αυτόν τον τρόπο θα εκμεταλλευτούμε τη δύναμη του DI container.
Θα μεταβούμε στο HomePresenter
το οποίο θα επεξεργαστούμε έτσι ώστε
να απαλλαγούμε από την εξάρτηση από το Nette\Database\Explorer
αντικαθιστώντας την με μια νέα εξάρτηση από τη νέα μας κλάση.
<?php
namespace App\UI\Home;
use App\Model\PostFacade;
use Nette;
final class HomePresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private PostFacade $facade,
) {
}
public function renderDefault(): void
{
$this->template->posts = $this->facade
->getPublicArticles()
->limit(5);
}
}
Στο τμήμα χρήσης, χρησιμοποιούμε το App\Model\PostFacade
, οπότε
μπορούμε να συντομεύσουμε τον κώδικα PHP σε PostFacade
. Ζητάμε αυτό το
αντικείμενο στον κατασκευαστή, το γράφουμε στην ιδιότητα $facade
και το χρησιμοποιούμε στη μέθοδο renderDefault.
Το τελευταίο βήμα που απομένει είναι να διδάξουμε στον περιέκτη DI να
παράγει αυτό το αντικείμενο. Αυτό συνήθως γίνεται με την προσθήκη ενός
σημείου αναφοράς στο αρχείο config/services.neon
στην ενότητα
services
, δίνοντας το πλήρες όνομα της κλάσης και τις παραμέτρους
του κατασκευαστή. Αυτό το καταχωρεί, τρόπον τινά, και το αντικείμενο
καλείται στη συνέχεια service. Χάρη σε κάποια μαγεία που ονομάζεται αυτόματη σύνδεση, συνήθως δεν
χρειάζεται να καθορίσουμε τις παραμέτρους του κατασκευαστή, επειδή το
DI θα τις αναγνωρίσει και θα τις περάσει αυτόματα. Έτσι, θα ήταν αρκετό
να δώσουμε απλώς το όνομα της κλάσης:
...
services:
- App\Model\PostFacade
Ωστόσο, δεν χρειάζεται να προσθέσετε ούτε αυτή τη γραμμή. Στην
ενότητα search
στην αρχή του services.neon
ορίζεται ότι όλες οι
κλάσεις που τελειώνουν με -Facade
ή -Factory
θα αναζητηθούν
αυτόματα από το DI, κάτι που ισχύει και για το PostFacade
.
Περίληψη
Η κλάση PostFacade
ζητάει το Nette\Database\Explorer
σε έναν
κατασκευαστή και επειδή αυτή η κλάση είναι καταχωρημένη στον περιέκτη
DI, ο περιέκτης δημιουργεί αυτή την περίπτωση και την περνάει. Το DI με
αυτόν τον τρόπο δημιουργεί μια περίπτωση PostFacade
για εμάς και την
περνάει σε έναν κατασκευαστή στην κλάση HomePresenter που τη ζήτησε. Κάτι σαν
μια κούκλα Matryoshka του κώδικα :) Όλα τα συστατικά ζητούν μόνο αυτό που
χρειάζονται και δεν τα ενδιαφέρει πού και πώς δημιουργείται. Η
δημιουργία αναλαμβάνεται από το DI container.
Εδώ μπορείτε να διαβάσετε περισσότερα για το dependency injection, και για τη διαμόρφωση.