2017-05-15 5 views
0

私はIntegrationBundle/Resources/config/services.ymlで以下のサービス定義を持っている:Symfonyコマンドからの呼び出しサービスが失敗します。「アプリケーションインスタンスがまだ設定されていないため、コンテナを取得できません。エラー、なぜですか?

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']] 
    ... 

私はsymfonyのコマンド内からmain.apiにアクセスする必要があると、これは私がそれをやっている方法です:

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が、のどれを読んでてきました彼らは私を助けます。

私に何か助けてもらえますか?私は何が欠けているのですか?

+1

問題は、数量入力オプションを構築する際に、コンテナにアクセスしようとしてあります。既定値-1を設定し、executeメソッドで実際の値を設定します。 – Cerad

+0

そして私はあなたが望んでいないことを知っていますが、実際にはコマンドをサービスとして定義し、必要なものだけを注入する必要があります。おそらく、他のすべてのクラスにコンテナを注入する本当の理由はありません。 – Cerad

+0

@Ceradコマンドをサービスとして定義すると、それをコマンド自体としてどうやって使うのですか?私の懸念はあります: "わかりました、私はサービスとしてコマンドを定義し、コマンドだけでコンテナを注入する、それは何"?私はそのコマンドをどのように呼び出すべきですか? – ReynierPM

答えて

1

私の最初のコメントでは、configureがコンストラクタから直接呼び出されたので、コンテナがまだ注入されていないので、configure()からgetContainerを呼び出すことはできません。 executeメソッドでパラメータを取得する必要があります。

コマンドをサービスとして定義し、実際に必要なサービスを注入する方法があります。例えば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%'] 
関連する問題