- Symfony 教程
- Symfony - 主页
- Symfony - 简介
- Symfony - 安装
- Symfony - 架构
- Symfony - 组件
- Symfony - 服务容器
- Symfony - 事件和事件监听器
- Symfony - 表达
- Symfony - 捆绑包
- 创建一个简单的 Web 应用程序
- Symfony - 控制器
- Symfony - 路由
- Symfony - 视图引擎
- Symfony - Doctrine ORM
- Symfony - 表单
- Symfony - 验证
- Symfony - 文件上传
- Symfony - Ajax 控制
- Cookie 和会话管理
- Symfony - 国际化
- Symfony - 日志记录
- Symfony - 电子邮件管理
- Symfony - 单元测试
- Symfony - 高级概念
- Symfony - REST 版
- Symfony - CMF 版
- 完整的工作示例
- Symfony 有用资源
- Symfony - 快速指南
- Symfony - 有用的资源
- Symfony - 讨论
Symfony - 服务容器
在任何应用程序中,对象往往会随着应用程序的增长而增加。随着对象的增加,对象之间的依赖关系也会增加。为了成功的应用程序,需要正确处理对象依赖性。
正如组件一章中所讨论的,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')));
最后,我们注册了两个类,Greeter和User,它们之间有很强的关系。现在,我们可以安全地从容器中获取具有正确配置的 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/config和symfony/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']]
现在,可以使用FileLoader和YamlFileLoader加载和配置services.yml,如以下代码所示。
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
<?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(); ?>
服务.yml
parameters: greeter.text: 'Hello' services: greeter: class: Greeter arguments: ['%greeter.text%'] user: class: User calls: - [setGreeter, ['@greeter']]
Symfony Web 框架广泛使用依赖注入组件。所有组件都受集中式服务容器的约束。Symfony Web框架通过container属性公开其所有Controller中的容器。我们可以通过它获取在其中注册的所有对象,例如记录器、邮件程序等。
$logger = $this->container->get('logger'); $logger->info('Hi');
要查找容器中注册的对象,请使用以下命令。
cd /path/to/app php bin/console debug:container
在安装章节中创建的hello Web 应用程序中有大约 200 多个对象。