Symfony 控制台应用程序:依赖注入

Posted

技术标签:

【中文标题】Symfony 控制台应用程序:依赖注入【英文标题】:Symfony console application: dependency injection [duplicate] 【发布时间】:2014-11-15 13:01:46 【问题描述】:

这里是 Symfony 新手。在阅读了一些 Symfony 文档和 SO 的一些答案之后,我现在几乎完全糊涂了。 我正在尝试使用控制台应用程序组件并创建一个小型 db-aware 控制台应用程序。

许多人说,为了使用 Symfony 的 DI 功能,我的命令类不是从 Symfony\Component\Console\Command\Command 而是从 ContainerAwareCommand 继承就足够了。 但是,当我尝试此操作时,我在 application::getKernel() 调用上收到 Method Not Found 错误。

我感觉 DI 功能实际上在基于控制台组件的控制台应用程序中不可用。是否还有另一种基于成熟框架的 Symfony 控制台应用程序?

我非常喜欢控制台组件 Symfony\Component\Console\Application 提供的简单框架。但问题是——依赖注入和 DBAL 该怎么办?我发现的所有示例似乎都引用了完整的 Symfony 框架,让我更加卡住了。

【问题讨论】:

鉴于您是 S2 的新手,我建议您使用完整的框架来开始。让您的应用程序运行并获得一些使用组件的经验。然后你可以试着把东西去掉。特别是如果您想访问 Doctrine 2 DBAL。它的配置有点痛苦。 【参考方案1】:

如果有人偶然发现同样的问题,请快速更新我的进度。

    我在我的项目中加入了 php-DI 依赖注入框架,它似乎在没有配置的情况下运行得相当好(到目前为止) - 实际上,它通过反射计算出很多东西。 同样,Doctrine\DBAL 作为独立库包含在内(我选择反对它的 O/RM 部分,因为它确实是一个小项目,而且我在使用 SQL 方面比其他任何东西都更稳固)并且连接由连接提供者简单地返回,该连接提供者在 DI 需要的任何地方注入。

我想不通的一件事是如何在没有我帮助的情况下让 DI 库实例化命令类,所以我实际上不得不将容器本身注入到我重写的应用程序类中并重写 getDefaultCommands() 我然后手动将实例从容器中拉出。不理想,但现在必须这样做。

【讨论】:

嗨,这里是 PHP-DI 的作者。这是一个如何将它与 Symfony 控制台组件(在 Symfony 框架之外)一起使用的示例:github.com/mnapoli/IsItMaintained/blob/master/bin/console 如果您有任何问题,请在 *** 上使用php-di 标签或在聊天中的头提问:gitter.im/mnapoli/PHP-DI跨度> 感谢您的链接。好吧,我最终做了类似的事情,除了我开始(甚至在集成 DI 之前)通过在应用程序类中创建一些命令作为默认命令。因此,为了继续沿着这条路前进,我必须将容器注入应用程序类并在那里拉取命令实例。暂时还可以。【参考方案2】:

如果您的命令扩展 ContainerAwareCommand

...
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
...

class MyCommand extends ContainerAwareCommand

DI 容器可通过getContainer() 方法获得。 (就像在标准控制器中一样),例如:

$this->validator = $this->getContainer()->get('validator');

【讨论】:

感谢您的回答。为使上述 sn-p 有效,应用程序对象是如何构造的?当我尝试您的建议时,我收到了我在问题中提到的错误(未找到 Application::getKernel() 方法)。这是有道理的,因为我正在构建的应用程序是 Symfony\Component\Console\Application 的一个实例,它没有内核 你没有使用全栈框架?所以这很正常,你需要自己构建容器并注入到命令中。 不,我不是!该应用程序不够大,无法带入重型枪支。这就是问题所在。由于某种原因,文档对此非常模糊。因此,Symfony\Component\Console\Application 不等于我们为自己创建的容器。 查看这篇博文:dcousineau.com/blog/2013/03/28/…【参考方案3】:

我不知道你的问题是否仍然相关,但我有一个答案,因为我在这里偶然发现了同样的问题。

您只需自己创建内核并将其提供给扩展基本 \Symfony\Component\Console\Application 的 \Symfony\Bundle\FrameworkBundle\Console\Application。

<?php
// CronRun.php

require __DIR__.'/../../../../vendor/autoload.php';
require_once __DIR__.'/../../../../app/AppKernel.php';

$kernel = new AppKernel('prod', false);
$kernel->loadClassCache();

$application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
$application->add(new \KingdomHall\TaskBundle\Command\CronCommand());
$input = new \Symfony\Component\Console\Input\StringInput('k:c:r');
$application->run($input);

【讨论】:

以上是关于Symfony 控制台应用程序:依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

树枝扩展中的 Symfony 依赖注入

Symfony依赖注入将类型的所有类作为参数注入

云客Drupal8源码分析之服务容器及Symfony依赖注入组件

译深入研究 Laravel 的依赖注入容器

Symfony2功能测试用例不包括自定义依赖注入配置参数

Symfony 控制器作为服务参数未注入