【问题标题】:Symfony: tagging a command with console.command doesn't seem to workSymfony:用 console.command 标记命令似乎不起作用
【发布时间】:2013-05-23 10:02:08
【问题描述】:

默认情况下,Symfony 会尝试扫描每个捆绑目录以查找名为“Command”的文件夹,并在其中搜索 Console\Command 类。

但是,当您想在控制台命令中使用 DIC 和 DI 时,还有另一种方法可以实现这一点。根据this article,应该可以使用依赖注入容器加载控制台命令,所以我尝试了。

我做了一个service.xml:

<services>
    <service id="atlas_cli.helper.anonymize" class="AtlasCliBundle\Services\AnonymizerHelperService" public="false" />
    <service id="atlas_cli.helper.dbconfiguration" class="AtlasCliBundle\Services\ConfigurationHelperService" public="false" />
    <service id="atlas_cli.helper.schemadump" class="AtlasCliBundle\Services\SchemaDumpHelperService" public="false" />
    <service id="atlas_cli.helperset" class="Symfony\Component\Console\Helper\HelperSet" />

    <service id="atlas_cli.command.anonymize" class="AtlasCliBundle\Command\AnonymizeCommand" public="true">
        <tag name="console.command" />
        <call method="setHelperSet">
            <argument type="service" id="atlas_cli.helperset" />
        </call>
        <call method="setAnonymizeHelper">
            <argument type="service" id="atlas_cli.helper.anonymize" />
            <argument type="string">dbanonymizer</argument>
        </call>
        <call method="setDbConfigurationHelper">
            <argument type="service" id="atlas_cli.helper.dbconfiguration" />
            <argument type="string">dbconfiguration</argument>
        </call>
    </service>

    <service id="atlas_cli.command.schema" class="AtlasCliBundle\Command\SchemaCommand" public="true">
        <tag name="console.command" />
        <call method="setHelperSet">
            <argument type="service" id="atlas_cli.helperset" />
        </call>
        <call method="setDbConfigurationHelper">
            <argument type="service" id="atlas_cli.helper.dbconfiguration" />
            <argument type="string">dbconfiguration</argument>
        </call>
        <call method="setSchemadumpHelper">
            <argument type="service" id="atlas_cli.helper.schemadump" />
            <argument type="string">schemadump</argument>
        </call>
    </service>
</services>

如您所见,我配置了 2 个命令匿名化和模式。这些命令在运行 app/console 时可用,但永远不会调用 set 方法(例如 setDbConfigurationHelper)。

我使用 Symfony 2.1,但我在 grep -ris "console\.command" * 上搜索了完整的 Symfony 框架代码,但对于 Symfony 2.3 来说,这并没有给出任何有用的结果。

标签 console.command 不再支持了吗?如果答案是肯定的,您建议使用什么来处理我的命令类中的依赖关系?

谢谢!!

【问题讨论】:

  • 您传递到服务中的附加字符串是什么?
  • 字符串是助手的别名(可选)。

标签: symfony dependency-injection


【解决方案1】:

console.command 标签已在 Symfony 2.4 中引入

对于 Symfony 2.3 及更低版本,将 Bundle::registerCommands 覆盖为如下内容:

<?php

namespace Acme\DemoBundle;

use Symfony\Component\Console\Application;

// ...

class AcmeDemoBundle extends Bundle
{
    public function registerCommands(Application $application)
    {
        $container = $application->getKernel()->getContainer();

        $application->add($container->get('atlas_cli.command.anonymize'));
        $application->add($container->get('atlas_cli.command.schema'));
    }
}

【讨论】:

  • 好的 Wouter,你能解释一下为什么我提到的文章是在谈论 console.command 标签吗?目前,我已经按照您建议的方式完全实现了它,但在我看来,它还不够迫切。无论如何,谢谢。
  • 我想是因为那篇文章是在 2010 年 3 月 15 日写的,当时 Symfony2 还在大力开发中。
  • 另外,那篇文章中的约定不再正确。
  • 您好 Wouter,感谢您的回答和 cmets。我选择了您的解决方案,因为它将以正确的方式使用 DIC。但我确认 Nifr 他的解决方案是“最简单”的解决方案。因此我会接受你的,因为它更适合我的需要。
  • 从 Symfony 2.4 开始:我们确实有一个名为 console.command 的标签,耶!
【解决方案2】:

让您的服务可用的最快解决方案是在您的命令中扩展Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand

use Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand;

class AnonymizeCommand extends ContainerAwareCommand
{ 
   // ...

然后你就可以像往常一样访问容器,并且可以使用

$myService = $this->container->get('service-name');

是的,我知道出于性能原因和其他各种原因,通常不建议注入整个容器...

在您的容器中调试标签(自 2.2 起可用)

app/console container:debug --tags

使用

调试 单个标签
app/console container:debug --tag=doctrine.event_listener

使用 grep 搜索与命令相关的标签(如果您在 Windows 上,则使用 findstr )

app/console container:debug --tags | grep command

如果您使用的是 symfony2,您将无法使用这些命令进行调试。在这种情况下,您应该尝试以下 2 个捆绑包。两者都提供有关 Profiler 中容器的信息。

【讨论】:

  • 谢谢,但我知道使用 ContainerAwareCommand 类,然后使用整个容器,但就像你说的那样,我不喜欢这种方法,因为它更难测试。我也在运行 Symfony 2.1。
  • 更新了答案,提示可以调试容器的捆绑包。请检查:)
  • 谢谢!我安装了这两个包,并且到目前为止我可以看到服务 atlas_cli.command.schema 已加载。但是你提到的捆绑包看起来不能处理标签?
  • 该死的我虽然他们能够 - 有一段时间没有使用它们了。为您考虑 2.1 的另一种解决方案。
  • 是的,我也是,但我看到命令是在 bundle 类的 registerCommands 函数中添加的。问题是您无法从那里访问 containerBuilder,因此您找不到任何标记的服务..
【解决方案3】:

搜索console.command并添加的组件是AddConsoleCommandPass:

public function build(ContainerBuilder $container) {
    parent::build($container); // TODO: Change the autogenerated stub
    $container->addCompilerPass(new AddConsoleCommandPass());
}

如果您在内核中添加 FrameworkBundle,这会自动完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-18
    • 2015-01-29
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多