在本文中,我们将看一些使用symfony DependencyInjection 组件的示例。您将学习依赖注入的基础知识,它允许代码更简洁、更模块化,并且您将了解如何在 php 应用程序中使用它和 Symfony 组件。
什么是 Symfony DependencyInjection 组件?
Symfony DependencyInjection 组件提供了一种在 PHP 应用程序中实例化对象和处理依赖管理的标准方法。DependencyInjection 组件的核心是一个包含应用程序中所有可用服务的容器。
在应用程序的引导阶段,您应该将应用程序中的所有服务注册到容器中。在稍后阶段,容器负责根据需要创建服务d. 更重要的是,容器还负责创建和注入服务的依赖项。
这种方法的好处是您不必对实例化对象的过程进行硬编码,因为将自动检测和注入依赖项。这会在应用程序的各个部分之间创建松散耦合。
在本文中,我们将探讨如何释放 DependencyInjection 组件的强大功能。像往常一样,我们将从安装和配置说明开始,我们将实施一些实际示例来演示关键概念。
安装和配置
在本节中,我们将继续安装 DependencyInjection 组件。我假设您已经在系统中安装了 Composer,因为我们需要它来安装 Packagist 提供的 DependencyInjection 组件。
所以继续使用以下命令安装 DependencyInjection 组件。
$composer require symfony/dependency-injection
那应该已经创建了composer.json文件,它应该如下所示:
{ "require": { "symfony/dependency-injection": "^4.1", } }
我们还将安装一些在我们的示例中有用的其他组件。
如果您想从 YAML 文件加载服务而不是在 PHP 代码中定义它,Yaml 组件可以帮助您将 YAML 字符串转换为与 PHP 兼容的数据类型,反之亦然。
$composer require symfony/yaml
最后,我们将安装 Config 组件,它提供了几个实用程序类来初始化和处理在 YAML、INI 和 XML 等不同类型的文件中定义的配置值。在我们的例子中,我们将使用它从 YAML 文件中加载服务。
$composer require symfony/config
让我们将composer.json文件修改为如下所示。
{ "require": { "symfony/dependency-injection": "^4.1", "symfony/config": "^4.1", "symfony/yaml": "^4.1" }, "autoload": { "psr-4": { "services\\": "src" }, "classmap": ["src"] } }
由于我们添加了一个新的类映射条目,让我们继续通过运行以下命令来更新Composer 自动加载器。
$composer dump -o
现在,您可以使用Services命名空间来自动加载src目录下的类。
这就是安装部分,但你应该如何使用它呢?实际上,只需将 Composer 创建的autoload.php文件包含在您的应用程序中即可,如下面的代码片段所示。
<?php require_once './vendor/autoload.php'; // application code ?>
如何使用容器
在本节中,我们将通过一个示例来演示如何将服务注入容器。容器应充当中央存储库,其中包含应用程序中的所有服务。稍后,我们可以根据需要使用容器来获取服务。
首先,让我们在src/DemoService.php中定义一个非常基本的服务,其内容如下。
<?php // src/DemoService.php namespace Services; class DemoService { public function helloWorld() { return "Hello World!\n"; } }
这是一个非常简单的服务,目前只是实现了该helloWorld方法。
接下来,继续在应用程序的根目录中创建包含以下内容的basic_container.php文件。
<?php // basic_container.php require_once './vendor/autoload.php'; use Symfony\Component\DependencyInjection\ContainerBuilder; // init service container $containerBuilder = new ContainerBuilder(); // add service into the service container $containerBuilder->register('demo.service', '\Services\DemoService'); // fetch service from the service container $demoService = $containerBuilder->get('demo.service'); echo $demoService->helloWorld();
首先,我们使用const ructor初始化ContainerBuilder对象。接下来,我们使用对象的方法将我们的自定义服务注入到容器中。充当我们服务的别名。new ContainerBuilder() registerContainerBuilder\Services\DemoServicedemo.service
最后,我们使用对象的get方法ContainerBuilder从容器中获取我们的服务并使用它来调用helloWorld方法。
这就是如何使用容器的基本演示。在下一节中,我们将扩展此示例以探索如何使用容器解决类依赖关系。
一个真实的例子
在本节中,我们将创建一个示例来演示如何使用 DependencyInjection 组件解决类依赖关系。
为了演示它,我们将创建一个新服务DependentService,该服务需要DemoService在上一节中创建的服务作为依赖项。因此,我们将看到在实例化服务DemoService时如何将服务作为依赖项自动注入。DependentService
继续创建包含以下内容的src/DependentService.phpDependentService文件来定义服务。
<?php // src/DependentService.php namespace Services; class DependentService { private $demo_service; public function __construct(\Services\DemoService $demoService) { $this->demo_service = $demoService; } public function helloWorld() { return $this->demo_service->helloWorld(); } }
如您所见,\Services\DemoService服务是实例化服务所必需的DependentService。
接下来,继续创建具有以下内容的di_container.php文件。
<?php // di_container.php require_once './vendor/autoload.php'; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; // init service container $containerBuilder = new ContainerBuilder(); // add demo service into the service container $containerBuilder->register('demo.service', '\Services\DemoService'); // add dependent service into the service container $containerBuilder->register('dependent.service', '\Services\DependentService') ->addArgument(new Reference('demo.service')); // fetch service from the service container $dependentService = $containerBuilder->get('dependent.service'); echo $dependentService->helloWorld();
我们使用相同的register方法将我们的自定义服务\Services\DependentService注入到容器中。
除此之外,我们还使用该addArgument方法通知容器有关DependentService服务的依赖关系。我们已经使用Reference该类来通知容器它需要在服务初始化demo.service时注入服务。dependent.service这样,依赖项会根据需要自动注入!
最后,我们使用对象的get方法从ContainerBuilder对象中获取dependent.service服务ContainerBuilder并使用它来调用helloWorld方法。
通过这种方式,DependencyInjection 组件提供了一种在应用程序中实例化对象和注入依赖项的标准方法。
如何使用 YAML 文件动态加载服务
在最后一节中,我们将探讨如何从 YAML 文件动态加载服务。基本上,我们将更新上一节中讨论的示例。
除了 DependencyInjection 组件,我们还需要另外两个 Symfony 组件来实现 YAML 示例——Config 和 Yaml。回想一下,我们已经在安装和配置部分安装了这两个组件以及 DependencyInjection 组件本身。所以我们可以走了!
继续在应用程序的根目录中创建包含以下内容的services.yaml文件。
services: demo.service: class: \Services\DemoService dependent.service: class: \Services\DependentService arguments: ["@demo.service"]
如您所见,使用 YAML 语法定义服务非常简单。要定义服务的依赖项,您需要使用arguments密钥。
接下来,继续创建具有以下内容的di_yaml_container.php文件。
<?php // di_yaml_container.php require_once './vendor/autoload.php'; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; // init service container $containerBuilder = new ContainerBuilder(); // init yaml file loader $loader = new YamlFileLoader($containerBuilder, new FileLocator(__DIR__)); // load services from the yaml file $loader->load('services.yaml'); // fetch service from the service container $serviceOne = $containerBuilder->get('dependent.service'); echo $serviceOne->helloWorld();
除了我们从services.yaml文件中加载服务而不是在 PHP 代码本身中定义它之外,一切都几乎相同。这允许动态定义应用程序依赖项。
结论
Symfony DependencyInjection 组件在本教程中占据了中心位置。我们看到了如何安装和配置 DependencyInjection,以及如何使用它的一些真实示例。