Symfony - Conteneur de services

Dans toute application, les objets ont tendance à augmenter à mesure que l'application se développe. À mesure que les objets augmentent, la dépendance entre les objets augmente également. La dépendance d'objet doit être gérée correctement pour une application réussie.

Comme indiqué dans le chapitre Composants, Symfony fournit un composant simple et efficace, DependencyInjectionpour gérer la dépendance aux objets. Un conteneur de services est un conteneur d'objets avec une dépendance correctement résolue entre eux. Apprenons à utiliser le composant DependencyInjection dans ce chapitre.

Créons un Greeterclasse. Le but de la classe Greeter est de saluer l'utilisateur comme indiqué dans l'exemple suivant.

$greeter = new Greeter('Hi'); 
$greeter->greet('Jon'); // print "Hi, Jon"

Le code complet de la classe Greeter est le suivant.

class Greeter { 
   private $greetingText; 
   
   public function __construct($greetingText) { 
      $this->greetingText = $greetingText; 
   }  
   public function greet($name) { 
      echo $this->greetingText . ", " . $name . "\r\n"; 
   } 
}

Maintenant, ajoutons la classe Greeter au conteneur de service. Symfony fournitContainerBuilderpour créer un nouveau conteneur. Une fois le conteneur créé, la classe Greeter peut y être enregistrée à l'aide de la méthode register du conteneur.

use Symfony\Component\DependencyInjection\ContainerBuilder; 
$container = new ContainerBuilder(); 
$container 
   ->register('greeter', 'Greeter') 
   ->addArgument('Hi');

Ici, nous avons utilisé un argument statique pour spécifier le texte de salutation, Salut. Symfony fournit également un réglage dynamique des paramètres. Pour utiliser un paramètre dynamique, nous devons choisir un nom et le spécifier entre% et le paramètre peut être défini à l'aide du conteneursetParameter méthode.

$container = new ContainerBuilder(); 
$container 
   ->register('greeter', 'Greeter') 
   ->addArgument('%greeter.text%');  
$container->setParameter('greeter.text', 'Hi');

Nous avons enregistré une classe Greeter avec un réglage approprié. Maintenant, nous pouvons demander au conteneur de fournir un objet Greeter correctement configuré en utilisant le conteneurget méthode.

$greeter = $container->get('greeter'); 
$greeter->greet('Jon'); // prints "Hi, Jon"

Nous avons enregistré avec succès une classe, Greeter dans le conteneur, l'avons récupérée dans le conteneur et l'avons utilisée. Maintenant, créons une autre classeUser, qui utilisent la classe Greeter et voient comment l'enregistrer.

class User { 
   private $greeter;  
   public $name; 
   public $age;  
   
   public function setGreeter(\Greeter $greeter) { 
      $this->greeter = $greeter; 
   }  
   public function greet() { 
      $this->greeter->greet($this->name); 
   } 
}

La classe User obtient la classe Greeter en utilisant l'une de ses méthodes setter,setGreeter. Pour ce scénario, Symfony fournit une méthode,addMethodCall et une classe, Reference pour faire référence à une autre classe comme indiqué dans le code suivant.

use Symfony\Component\DependencyInjection\Reference;  
$container 
   ->register('user', 'User') 
   ->addMethodCall('setGreeter', array(new Reference('greeter')));

Enfin, nous avons enregistré deux classes, Greeter et Useravoir une relation forte entre eux. Maintenant, nous pouvons récupérer en toute sécurité l'objet User avec la classe Greeter correctement configurée à partir du conteneur, comme indiqué dans le code suivant.

$container->setParameter('greeter.text', 'Hi'); 
$user = $container->get('user'); 
$user->name = "Jon"; 
$user->age = 20; 
$user->greet(); // Prints "Hi, Jon"

Nous avons vu comment configurer un objet dans un conteneur en utilisant PHP lui-même. Symfony fournit également d'autres mécanismes. Ce sont des fichiers de configuration XML et YAML. Voyons comment configurer un conteneur à l'aide de YAML. Pour cela, installezsymfony/config et symfony/yaml composants avec symfony/dependency-injection Composants.

cd /path/to/dir 
mkdir dependency-injection-example 
cd dependency-injection-example 
composer require symfony/dependency-injection 
composer require symfony/config 
composer require symfony/yaml

La configuration YAML sera écrite dans un fichier séparé, services.yml. La configuration YAML se compose de deux sections,parameters et services. La section Paramètres définit tous les paramètres requis. La section Services définit tous les objets. La section Services est divisée en plusieurs sections à savoir,class, arguments, et calls. Classe spécifie la classe réelle. Arguments spécifie les arguments du constructeur. Enfin, les appels spécifient les méthodes du setter. Une autre classe peut être référencée en utilisant le symbole @, @greeter.

parameters: 
   greeter.text: 'Hello' 
services: 
   greeter: 
      class: Greeter
      arguments: ['%greeter.text%'] 
   user: 
      class: User 
      calls: 
         - [setGreeter, ['@greeter']]

Maintenant, services.yml peut être chargé et configuré en utilisant FileLoader et YamlFileLoader comme indiqué dans le code suivant.

use Symfony\Component\Config\FileLocator; 
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;  

$yamlContainer = new ContainerBuilder(); 
$loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__)); 
$loader->load('services.yml');  

$yamlUser = $yamlContainer->get('user'); 
$yamlUser->name = "Jon"; 
$yamlUser->age = 25; 
$yamlUser->greet();

La liste complète des codes est la suivante.

main.php

<?php  
   require __DIR__ . '/vendor/autoload.php';  
   use Symfony\Component\DependencyInjection\ContainerBuilder; 
   use Symfony\Component\Config\FileLocator; 
   use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; 
   use Symfony\Component\DependencyInjection\Reference;  
   
   class Greeter { 
      private $greetingText; 
      
      public function __construct($greetingText) {
         $this->greetingText = $greetingText; 
      }  
      public function greet($name) { 
         echo $this->greetingText . ", " . $name . "\r\n"; 
      } 
   }  
   class User { 
      private $greeter;  
      public $name; 
      public $age;  
      
      public function setGreeter(\Greeter $greeter) { 
         $this->greeter = $greeter; 
      }  
      public function greet() { 
         $this->greeter->greet($this->name); 
      } 
   }  
   $container = new ContainerBuilder(); 
   $container 
      ->register('greeter', 'Greeter') 
      ->addArgument('%greeter.text%');  
   $container 
      ->register('user', 'User') 
      ->addMethodCall('setGreeter', array(new Reference('greeter')));
   
   $container->setParameter('greeter.text', 'Hi'); 
   $greeter = $container->get('greeter'); 
   $greeter->greet('Jon'); 
   
   $user = $container->get('user'); 
   $user->name = "Jon"; 
   $user->age = 20; 
   $user->greet();  
   
   $yamlContainer = new ContainerBuilder(); 
   $loader = new YamlFileLoader($yamlContainer, new FileLocator(__DIR__)); 
   $loader->load('services.yml');  

   $yamlHello = $yamlContainer->get('greeter'); 
   $yamlHello->greet('Jon'); 
   
   $yamlUser = $yamlContainer->get('user'); 
   $yamlUser->name = "Jon"; 
   $yamlUser->age = 25; 
   $yamlUser->greet();  
?>

services.yml

parameters: 
   greeter.text: 'Hello' 
services: 
   greeter: 
      class: Greeter 
      arguments: ['%greeter.text%'] 
   user: 
      class: User 
      calls: 
         - [setGreeter, ['@greeter']]

Le framework Web Symfony utilise largement le composant d'injection de dépendances. Tous les composants sont liés par le conteneur de service centralisé. Le framework Web Symfony expose le conteneur dans tous sesController à travers containerpropriété. Nous pouvons y enregistrer tous les objets, par exemple enregistreur, courrier électronique, etc.

$logger = $this->container->get('logger'); 
$logger->info('Hi');

Pour rechercher l'objet enregistré dans le conteneur, utilisez la commande suivante.

cd /path/to/app 
php bin/console debug:container

Il y a environ 200+ objets dans le hello application Web créée dans le chapitre d'installation.