Symfony - Service Container

In jeder Anwendung nehmen Objekte tendenziell zu, wenn die Anwendung wächst. Mit zunehmenden Objekten nimmt auch die Abhängigkeit zwischen den Objekten zu. Die Objektabhängigkeit muss für eine erfolgreiche Anwendung ordnungsgemäß behandelt werden.

Wie im Kapitel Komponenten erläutert, bietet Symfony eine einfache und effiziente Komponente: DependencyInjectionObjektabhängigkeit zu behandeln. Ein Service-Container ist ein Container mit Objekten, zwischen denen eine ordnungsgemäß aufgelöste Abhängigkeit besteht. In diesem Kapitel erfahren Sie, wie Sie die DependencyInjection-Komponente verwenden.

Lassen Sie uns eine erstellen GreeterKlasse. Der Zweck der Greeter-Klasse besteht darin, den Benutzer wie im folgenden Beispiel gezeigt zu begrüßen.

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

Der vollständige Code der Greeter-Klasse lautet wie folgt.

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

Fügen wir nun die Greeter-Klasse zum Service-Container hinzu. Symfony bietetContainerBuilderum einen neuen Container zu erstellen. Sobald der Container erstellt wurde, kann die Greeter-Klasse mithilfe der Registrierungsmethode des Containers registriert werden.

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

Hier haben wir statische Argumente verwendet, um den Begrüßungstext Hi anzugeben. Symfony bietet auch eine dynamische Einstellung von Parametern. Um einen dynamischen Parameter zu verwenden, müssen wir einen Namen auswählen und zwischen% angeben, und der Parameter kann mithilfe von Containern festgelegt werdensetParameter Methode.

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

Wir haben eine Greeter-Klasse mit der richtigen Einstellung registriert. Jetzt können wir den Container bitten, mithilfe des Containers ein ordnungsgemäß konfiguriertes Greeter-Objekt bereitzustellenget Methode.

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

Wir haben eine Klasse, Greeter, erfolgreich in den Container registriert, aus dem Container abgerufen und verwendet. Lassen Sie uns nun eine weitere Klasse erstellenUser, die die Greeter-Klasse verwenden und sehen, wie sie registriert wird.

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

Die User-Klasse ruft die Greeter- Klasse mit einer ihrer Setter-Methoden ab:setGreeter. Für dieses Szenario bietet Symfony eine Methode:addMethodCall und eine Klasse, Reference um auf eine andere Klasse zu verweisen, wie im folgenden Code gezeigt.

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

Schließlich haben wir zwei Klassen angemeldet, Greeter und Usereine starke Beziehung zwischen ihnen haben. Jetzt können wir das Benutzerobjekt mit der ordnungsgemäß konfigurierten Greeter-Klasse sicher aus dem Container abrufen, wie im folgenden Code gezeigt.

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

Wir haben gesehen, wie ein Objekt in einem Container mit PHP selbst konfiguriert wird. Symfony bietet auch andere Mechanismen. Dies sind XML- und YAML-Konfigurationsdateien. Lassen Sie uns sehen, wie ein Container mit YAML konfiguriert wird. Installieren Sie dazusymfony/config und symfony/yaml Komponenten zusammen mit symfony/dependency-injection Komponenten.

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

Die YAML-Konfiguration wird in eine separate Datei geschrieben. services.yml. Die YAML-Konfiguration besteht aus zwei Abschnitten:parameters und services. Der Abschnitt Parameter definiert alle erforderlichen Parameter. Der Abschnitt Dienste definiert alle Objekte. Der Bereich Dienstleistungen ist weiter in mehrere Abschnitte unterteilt, nämlichclass, arguments, und calls. Klasse gibt die tatsächliche Klasse an. Argumente gibt die Argumente des Konstruktors an. Schließlich geben Aufrufe die Setter-Methoden an. Eine andere Klasse kann mit dem @ -Symbol @greeter referenziert werden.

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

Jetzt, services.yml kann mit geladen und konfiguriert werden FileLoader und YamlFileLoader wie im folgenden Code gezeigt.

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();

Die vollständige Codeliste lautet wie folgt.

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']]

Das Symfony-Webframework verwendet die Komponente zur Abhängigkeitsinjektion in großem Umfang. Alle Komponenten sind an den zentralen Servicecontainer gebunden. Das Symfony-Webframework macht den Container in all seinen Funktionen verfügbarController durch containerEigentum. Wir können alle darin registrierten Objekte, z. B. Logger, Mailer usw., darüber registrieren lassen.

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

Verwenden Sie den folgenden Befehl, um das im Container registrierte Objekt zu finden.

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

Es gibt mehr als 200 Objekte in der hello Web-App im Installationskapitel erstellt.