Ένα από τα σημεία κλειδιά του Laravel είναι το Service Container, αυτό πρακτικά είναι ένα εργαλείο που μας βοηθάει στη διαχείριση των κλάσεων και των εξαρτήσεων τους από άλλες κλάσεις ή παραμέτρους. Με λίγα λόγια αυτοματοποιεί το Dependency Injection όταν δημιουργούμε καινούργια στιγμιότυπα δηλαδή objects μέσα σε ένα web application.

Η διαχείριση των dependencies είναι ένα βασικό σημείο γιατί δεν χρειάζεται να γνωρίζουμε και να θυμόμαστε τις εξαρτήσεις και τις παραμέτρους, όταν χρειαστούμε ένα καινούργιο στιγμιότυπο αντικειμένου, τότε το καλούμε και είναι ευρεία διαθέσιμο σε όλη την εφαρμογή μόνο με το όνομα του. Γενικά αυτού του τύπου εργαλεία ονομάζονται DI containers και μπορουμε να τα συναντήσουμε και σε άλλα frameworks

Οπότε χρησιμοποιώντας αυτή τη τεχνική μπορεί να μειωθεί σημαντικά ο κώδικας που επαναλαμβάνεται και να κρατήσει σε minimal επίπεδο τους controllers στο MVC, δηλαδή να μην έχουμε το φαινόμενο των Fat Controllers και Fat Models και επιπλέον ο κώδικας να μπορεί να γίνει testable.

Οι κλάσεις που ορίζονται στο container ονομάζονται services provider και μπορούν να κληθούν στους controllers και με type hinting

class LocationController { 

    public function index(GoogleMap $map) {

        $coordinates = $map->getCoordinates("Leof 62 Martiron 10"); 

    }
}

Τι είναι το Service Container

Το service container στο Laravel είναι το κλειδί του συστήματος όπου επιτρέπει τη διαχείριση του Dependency Injection. Αυτό σημαίνει ότι μπορεί να διαχειριστεί τις κλάσεις και τις εξαρτήσεις τους ώστε όταν δημιουργηθεί ένα στιγμιότυπο εκεί αυτόματα να επιλυθούν και να βρεθούν από ποιες κλάσεις και παραμέτρους εξαρτάται.

Service providers

To Laravel διαθέτει δύο τύπους που είναι core services δηλαδή που υπάρχουν μέσα στο framework και τα services σε επίπεδο application δηλαδή που δημιουργεί ο web developer μέσα στο project και εξυπηρετούν συγκεκριμένες.

Γενικά αυτά έχουν δύο βασικά χαρακτηριστικά που είναι ότι επεκτείνουν την κλαση ( https://laravel.com/api/5.8/Illuminate/Support/ServiceProvider.html)

Για να δημιουργήσουμε 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.