📜  Symfony-服务容器

📅  最后修改于: 2020-10-19 03:13:16             🧑  作者: Mango


在任何应用程序中,对象往往随着应用程序的增长而增加。随着对象增加,对象之间的依赖性也增加。对于成功的应用程序,需要正确处理对象依赖性。

正如“组件”一章中讨论的那样,Symfony提供了一个简单有效的组件DependencyInjection来处理对象依赖性。服务容器是对象之间具有正确解析的依赖关系的容器。让我们在本章中学习如何使用DependencyInjection组件。

让我们创建一个Greeter类。 Greeter类的目的是为了迎接用户,如以下示例所示。

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

Greeter类的完整代码如下。

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

现在,让我们将Greeter类添加到服务容器中。 Symfony提供了ContainerBuilder来创建一个新的容器。创建容器后,可以使用容器的register方法将Greeter类注册到其中。

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

在这里,我们使用了静态参数来指定问候语文本Hi。 Symfony还提供参数的动态设置。要使用动态参数,我们需要选择一个名称并在%之间指定,并且可以使用容器的setParameter方法设置该参数。

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

我们已经注册了具有适当设置的Greeter类。现在,我们可以要求容器使用容器的get方法提供正确配置的Greeter对象。

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

我们已经成功地将一个名为Greeter的类注册到了容器中,并从容器中获取并使用了它。现在,让我们创建另一个类User ,它使用Greeter类并查看如何注册。

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

User类使用其setter方法之一setGreeter获取Greeter类。对于这种情况,Symfony提供了一个方法addMethodCall和一个类Reference来引用另一个类,如以下代码所示。

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

最后,我们注册了两个类,即GreeterUser ,它们之间有很强的联系。现在,我们可以从容器中安全地获取具有正确配置的Greeter类的User对象,如以下代码所示。

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

我们已经看到了如何使用PHP本身在容器中配置对象。 Symfony还提供其他机制。它们是XML和YAML配置文件。让我们看看如何使用YAML配置容器。为此,请安装symfony / configsymfony / yaml组件以及symfony / dependency-injection组件。

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

YAML配置将写入一个单独的文件services.yml中。 YAML配置包括两部分,参数服务。参数部分定义了所有必需的参数。服务部分定义所有对象。服务部分进一步分为多个部分,即类,参数调用。类指定实际的类。参数指定构造函数的参数。最后,调用指定setter方法。可以使用@符号@greeter引用另一个类。

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

现在,services.yml可以加载和显示在下面的代码中使用FileLoaderYamlFileLoader配置。

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

完整的代码清单如下。

main.php

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

Symfony Web框架广泛使用依赖注入组件。所有组件都由集中式服务容器绑定。 Symfony Web框架通过容器属性在其所有Controller中公开该容器。我们可以通过它注册所有对象,例如记录器,邮件程序等。

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

要查找在容器中注册的对象,请使用以下命令。

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

在安装章节中创建的hello Web应用程序中大约有200多个对象。