I have the following services definition at 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']]
...
I need to access main.api
from within a Symfony Command and this is how I am doing it:
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')
));
}
}
Then I am trying the command as follow:
$ 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.
As you can see is failing and I am not sure what I am missing here. Below is a stack trace (if that help somehow):
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
I have been reading here (I do not want and do not need to define this command as a service), here, here and here but none of them help me.
Can any give me some help here? What I am missing?
As per my first comment, you cannot call getContainer from configure() as the container has not yet been injected since configure is called directly from the constructor. You will need to pull the parameter in the execute method.
An alternative (and perhaps a bit cleaner) approach is to define the command as a service and inject the services actually needed. http://symfony.com/doc/current/console/commands_as_services.html
For example:
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%']