Rey*_*rPM 2 php symfony symfony-console symfony-3.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']]
...
Run Code Online (Sandbox Code Playgroud)
我需要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')
));
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试如下命令:
$ 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.
Run Code Online (Sandbox Code Playgroud)
如您所见,失败了,我不确定这里缺少什么。以下是堆栈跟踪(如果有帮助的话):
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
Run Code Online (Sandbox Code Playgroud)
我一直在这里阅读(我不需要并且不需要将此命令定义为服务),这里,这里和这里,但是它们都没有帮助我。
有什么可以帮我的忙吗?我缺少什么?
根据我的第一句话,您不能从configure()调用getContainer,因为尚未直接从构造函数调用configure,因此尚未注入容器。您将需要在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%']
Run Code Online (Sandbox Code Playgroud)