发布于 2015-08-27 16:48:28 | 128 次阅读 | 评论: 0 | 来源: 网络整理
By default, Symfony will take a look in the Command
directory of each
bundle and automatically register your commands. If a command extends the
ContainerAwareCommand
,
Symfony will even inject the container.
While making life easier, this has some limitations:
Command
directory;configure()
method (because
setContainer
hasn’t been called yet);To solve these problems, you can register your command as a service and tag it
with console.command
:
# app/config/config.yml
services:
acme_hello.command.my_command:
class: AcmeHelloBundleCommandMyCommand
tags:
- { name: console.command }
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme_hello.command.my_command"
class="AcmeHelloBundleCommandMyCommand">
<tag name="console.command" />
</service>
</services>
</container>
// app/config/config.php
$container
->register('acme_hello.command.my_command', 'AcmeHelloBundleCommandMyCommand')
->addTag('console.command')
;
Imagine you want to provide a default value for the name
option. You could
pass one of the following as the 5th argument of addOption()
:
By extending ContainerAwareCommand
, only the first is possible, because you
can’t access the container inside the configure()
method. Instead, inject
any parameter or service you need into the constructor. For example, suppose you
have some NameRepository
service that you’ll use to get your default value:
// src/Acme/DemoBundle/Command/GreetCommand.php
namespace AcmeDemoBundleCommand;
use AcmeDemoBundleEntityNameRepository;
use SymfonyComponentConsoleCommandCommand;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleInputInputOption;
use SymfonyComponentConsoleOutputOutputInterface;
class GreetCommand extends Command
{
protected $nameRepository;
public function __construct(NameRepository $nameRepository)
{
$this->nameRepository = $nameRepository;
parent::__construct();
}
protected function configure()
{
$defaultName = $this->nameRepository->findLastOne();
$this
->setName('demo:greet')
->setDescription('Greet someone')
->addOption('name', '-n', InputOption::VALUE_REQUIRED, 'Who do you want to greet?', $defaultName)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$name = $input->getOption('name');
$output->writeln($name);
}
}
Now, just update the arguments of your service configuration like normal to
inject the NameRepository
. Great, you now have a dynamic default value!
警告
Be careful not to actually do any work in configure
(e.g. make database
queries), as your code will be run, even if you’re using the console to
execute a different command.