2

我在以下服务定义IntegrationBundle/Resources/config/services.yml

services:
  event.subscriber.params.extractor:
    class: IntegrationBundle\Middleware\EventSuscriberParamsExtractor

  main.api:
    class: IntegrationBundle\API\MainAPI
    calls:
      - [setContainer, ['@service_container']]
  order.push.api:
    class: IntegrationBundle\API\OrderPushAPI
    calls:
      - [setContainer, ['@service_container']]

  process.account.api:
    class: IntegrationBundle\API\ProcessAccountData
    arguments:
      - '@event.subscriber.params.extractor'
    calls:
      - [setContainer, ['@service_container']]
  ...

我需要main.api从 Symfony 命令中访问,这就是我的做法:

namespace IntegrationBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Command\LockableTrait;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class SchneiderAPICommand extends ContainerAwareCommand
{
    use LockableTrait;

    protected function configure()
    {
        $this
            ->setName('api:execute')
            ->setDefinition(
                new InputDefinition([
                    new InputOption('source', '', InputArgument::OPTIONAL, '', 'Wonderware'),
                    new InputOption('object', '', InputArgument::OPTIONAL, '', 'Account,AgreementHistory'),
                    new InputOption('quantity', '', InputArgument::OPTIONAL, '', $this->getContainer()->getParameter('api_items_to_process')
                    ),
                ])
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // Prevent multiple executions of a console command
        if (!$this->lock()) {
            $output->writeln('The command is already running in another process.');

            return 0;
        }

        $output->writeln($this->getContainer()->get('main.api')->execute(
            $input->getOption('source'),
            str_replace(',', '|', $input->getOption('object')),
            $input->getOption('quantity')
        ));
    }
}

然后我尝试如下命令:

$ bin/console api:execute --source=Wonderware --object=Account --quantity=50 -vvv  

  [LogicException]                                                               
  The container cannot be retrieved as the application instance is not yet set.  

如您所见,失败了,我不确定我在这里缺少什么。下面是一个堆栈跟踪(如果有帮助的话):

Exception trace:
 () at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php:40
 Symfony\Bundle\FrameworkBundle\Command\ContSchneiderainerAwareCommand->getContainer() at /var/www/html/symfony/src/IntegrationBundle/Command/MainAPICommand.php:38
 IntegrationBundle\Command\MainAPICommand->configure() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php:63
 Symfony\Component\Console\Command\Command->__construct() at n/a:n/a
 ReflectionClass->newInstance() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Bundle/Bundle.php:193
 Symfony\Component\HttpKernel\Bundle\Bundle->registerCommands() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:135
 Symfony\Bundle\FrameworkBundle\Console\Application->registerCommands() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:108
 Symfony\Bundle\FrameworkBundle\Console\Application->all() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:72
 Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/symfony/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:124
 Symfony\Component\Console\Application->run() at /var/www/html/symfony/bin/console:28

我一直在阅读here(我不想也不需要将此命令定义为服务),hereherehere,但它们都没有帮助我。

有人可以在这里给我一些帮助吗?我错过了什么?

4

1 回答 1

5

根据我的第一条评论,您不能从 configure() 调用 getContainer ,因为尚未注入容器,因为 configure 是直接从构造函数调用的。您将需要在执行方法中提取参数。

另一种(可能更简洁)的方法是将命令定义为服务并注入实际需要的服务。 http://symfony.com/doc/current/console/commands_as_services.html

例如:

class SchneiderAPICommand extends Command
{
    private $mainAPI;
    private $defaultQuaity;
    public function __construct(MainAPI $mainAPI, $defaultQuantity)
    {
        parent::__construct();
        $this->mainAPI = $mainAPI;
        $this->defaultQuanity = $defaultQuanity;
    }
    protected function configure() {
        ...
        new InputOption('quantity', '', InputArgument::OPTIONAL, '', $this->defaultQuantity),

# services.yml
main.api.command:
    class: MyBundle\Command\SchneiderAPICommand
    tags: [{ name: console.command }] # This makes it a command
    arguments: ['@main.api','%api_items_to_process%']
于 2017-05-15T18:45:18.483 回答