Το Laravel φημίζεται για το κομψό και περιεκτικό συντακτικό και για κάποια δυνατά χαρακτηριστικά που έχει, αλλά η πραγματική του δύναμη web framework βρίσκεται στο Service Container. Αυτή η δυνατότητα είναι συνήθως παραγκωνισμένη και κρυμμένη να βελτιώσει τον τρόπο με τον οποίο διαχειρίζεστε τις εξαρτήσεις, καθιστώντας τον κώδικα καθαρό και συντηρήσιμο.
Ωστόσο, παρά τις δυνατότητές του, οι προγραμματιστές συχνά δεν το χρησιμοποιούν απλώς και μόνο επειδή δεν γνωρίζουν πώς να το αξιοποιήσουν αποτελεσματικά.
Η κατανόηση του Laravel Service Container είναι απαραίτητη όχι μόνο για την απλοποίηση του κώδικά σας, αλλά και για την ενίσχυση της συνολικής αρχιτεκτονικής των εφαρμογών δηλαδή το web application architecture. Είτε είστε αρχάριος που μόλις ξεκινάτε είτε έμπειρος προγραμματιστής που επιθυμεί να βελτιστοποιήσει τα υπάρχοντα projects, η κατανόηση του Service Container θα αλλάξει τα δεδομένα. Σε αυτό το άρθρο, θα εξερευνήσουμε τις βασικές αρχές και λειτουργίες του Laravel Service Container, βοηθώντας σας να κάνετε code refactoring έαν δεν το έχετε κάνει ήδη.
Ένα από τα σημεία κλειδιά στο Laravel είναι το Service Container, αυτό πρακτικά είναι ένα εργαλείο που μας βοηθάει στη διαχείριση των κλάσεων και των εξαρτήσεων τους από άλλες κλάσεις ή παραμέτρους. Με λίγα λόγια αυτοματοποιεί το Dependency Injection όταν δημιουργούμε καινούργια στιγμιότυπα δηλαδή objects μέσα σε ένα web application.
Η διαχείριση των dependencies είναι ένα βασικό σημείο γιατί δεν χρειάζεται να γνωρίζουμε και να θυμόμαστε τις εξαρτήσεις και τις παραμέτρους, όταν χρειαστούμε ένα καινούργιο στιγμιότυπο αντικειμένου, τότε το καλούμε και είναι ευρεία διαθέσιμο σε όλη την εφαρμογή μόνο με το όνομα του. Γενικά αυτού του τύπου εργαλεία ονομάζονται DI containers και μπορούμε να τα συναντήσουμε και σε άλλα frameworks
Πότε να το χρησιμοποιήσετε
- Αν γράφετε ένα πακέτο Laravel που σκοπεύετε να μοιραστείτε με άλλους προγραμματιστές Laravel, μπορεί να κάνουμε bind το πακέτο στο container
- Εάν η κλάση σας χρειάζεται ένα αρχικό όρισμα πριν από τη δημιουργία του στιγμιότυπου της κλάσης.
- Όταν κάνουμε ένα καινούργιο Facade
Οπότε χρησιμοποιώντας αυτή τη τεχνική μπορεί να μειωθεί σημαντικά ο κώδικας που επαναλαμβάνεται και να κρατήσει σε minimal επίπεδο τους controllers στο Model-View-Controller MVC ενός web application architecture, δηλαδή να μην έχουμε το φαινόμενο των Fat Controllers και Fat Models ώστε ο κώδικας να μπορεί να γίνει testable.
Οι κλάσεις που ορίζονται στο container ονομάζονται services provider και μπορούν να κληθούν στους controllers και με type hinting
Τι είναι το type hinting;
To type hinting μας επιτρέπει να προσδιορίσουμε τον αναμενόμενο τύπο δεδομένων (data types) για τις παραμέτρους μιας συνάρτησης αλλά και και τι επιστρεφόμενες τιμές
use app\services\GoogleMap;
class LocationController { public function index(GoogleMap $map) { $coordinates = $map->getCoordinates("Leof 62 Martiron 10"); } }
Στο παραπάνω παράδειγμα το Type-Hint μια Custom κλάση με το όνομα GoogleMap.
Επιπλέον το type-hint μπορεί να επιστρέφει ένα στο στιγμιότυπο ενός μοντέλου, μία συλλογή μοντέλων δηλαδή Collection,
Service Container πως σχετίζεται με dependency injection
Το service container στο Laravel είναι το κλειδί του συστήματος όπου επιτρέπει τη διαχείριση του Dependency Injection. Αυτό σημαίνει ότι μπορεί να διαχειριστεί τις κλάσεις και τις εξαρτήσεις τους ώστε όταν δημιουργηθεί ένα στιγμιότυπο εκεί αυτόματα να επιλυθούν και να βρεθούν από ποιες κλάσεις και παραμέτρους εξαρτάται.
Service provider
To Laravel διαθέτει δύο τύπους που είναι core services δηλαδή που υπάρχουν μέσα στο framework και τα services σε επίπεδο application δηλαδή που δημιουργεί ο web developer μέσα στο project και εξυπηρετούν συγκεκριμένες υπηρεσίες.
Οι services providers που θα φορτωθούν εξαργής βρίσκονται στο αρχείο config/app.php
Γενικά αυτά έχουν δύο βασικά χαρακτηριστικά που είναι ότι επεκτείνουν την κλαση (Illuminate\Support\ServiceProvider
)
Για να δημιουργήσουμε service providers μπορούν να δημιουργηθούν με το CLI
php artisan make:provider CustomServiceProvider
Αφού δημιουργήσουμε μια τέτοια κλάση τότε θα δούμε ότι περιλαμβάνει δύο βασικές μεθόδους που είναι
Μέθοδος register
Αυτή η μέθοδος χρησιμοποιείται για να ορίσει πως θα γίνει bind στο service container όπου μπορούν να γίνουν τα binds χειροκίνητα ή μέσω συγκεκριμένων properties που ονομάζονται bindings και singletons.
Τα service provider και γενικά οι εξαρτήσεις μπορούν προστεθούν σε αυτήν
public function register() { $this->app->singleton('custom-logic', function () { $baseNumber = 123; return new \App\MyCustomLogic($baseNumber); });
Τα δυο βασικά bindings που έχουν εδώ είναι bind και το singleton, η διαφορά τους εδώ είναι στο χρόνο εκτέλεσης και διατήρησης του object. Στη πρώτη περίπτωση δηλαδή στο bind, όταν γίνει κλήση για τη δημιουργία στιγμιότυπου-αντικειμένου το αντικείμενο δημιουργείται από την αρχή κάθε φορά που γίνεται κλήσh
Ενώ το bind με singleton το στιγμιότυπο δημιουργείται τη πρώτη φορά και η κατάσταση του και τα properties διατηρούνται καθόλα τη φάση της εκτέλεσης της εφαρμογής
Μέθοδος boot
Όταν έχουν γίνει register όλοι οι services provider οι επόμενοι μέθοδος που καλείται είναι η boot, εδώ μπορούμε να έχουμε πρόσβαση σε όλα τα services που έχουν γίνει register στη method register
Παραδείγματα χρήσης αυτής τη μεθόδους η δημιουργία ενός custom validator
Validator::extend('custom_validator', function ($attribute, $value, $parameters, $validator) { // validation logic });
Ο διαμερισμός δεδομένων μεταξύ multiple view
View::share('key', 'value');
Ορισμός των providers
Τα services providers γίνονται register στο config/app.php αρχείο οπότε στο provider array θα πρέπει να εισάγουμε το service που μόλις δημιουργήσαμε
'providers' => [ App\Providers\CustomeServiceProvider::class, ]
Όταν γίνει αυτό μπορούν να χρησιμοποιηθούν μέσα στο controllers, τα models σε άλλους service providers.
Στο μοντέρνο web development η χρήση μια αρχιτεκτονικής για τη διαχείριση των εξαρτώμενων κλάσεων και τον παραμέτρων του κρίνεται σχεδόν απαραίτητη.