I'm trying to get a configuration parameter into a command.
I have added the parameter in the app/config/config.yml
under the parameters
key.
I can use it in a Controller using $this->getParameter("PRAMETER_NAME")
in an action to do some stuff manually.
I'm writing a command to do the same stuff automatically with a CRON job.
I can't find how to get the parameter in the command.
In Symfony 3.4 or later, the recommended approach is to use Autowiring and Argument Binding. Allowing for the declaration of the variable name to be "bound" as an argument for ALL services defined in the config file, without needing to explicitly specify each service the parameter is used in.
In the same configuration file that defines the command service and autowiring, add the bind
option to the _defaults
specification, along with the desired variable name for the parameter.
app/config/services.yml
parameters:
PARAMETER_NAME: 'test'
services:
_defaults:
bind:
$PARAMETER_NAME: '%PARAMETER_NAME%'
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'
# Additional Services Below Here
Afterwards, Symfony will automatically pass the parameter value to the bound variable name when it is specified as an argument for the service constructor.
src/AppBundle/Command/MyCommand.php
namespace AppBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command
{
private $PARAMETER_NAME;
public function __construct($PARAMETER_NAME)
{
$this->PARAMETER_NAME = $PARAMETER_NAME;
parent::__construct();
}
// ...
public function execute(InputInterface $input, OutputInterface $output)
{
dump($this->PARAMETER_NAME);
exit;
}
public static function getDefaultName()
{
return 'app:my_command';
}
}
Another approach, to avoid needing to override __construct
, is to inject the parameter value using a method, by extending the service definition using calls
.
app/config/services.yml
parameters:
PARAMETER_NAME: 'test'
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'
AppBundle\Command\MyCommand:
calls:
- [setParameterName, ['%PARAMETER_NAME%']]
# Additional Services Below Here
src/AppBundle/Command/MyCommand.php
namespace AppBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends Command
{
private $parameterName;
// ...
public function execute(InputInterface $input, OutputInterface $output)
{
dump($this->parameterName);
exit;
}
public function setParameterName($value)
{
$this->parameterName = $value;
}
}
Alternatively, dependency injection can be used to inject the Container or ParameterBag into the command, allowing it to function similarly to a Controller.
Injecting the entire Container or ParameterBag is highly discouraged. Only inject the parameter(s) and service(s) that are needed instead.
In either of the below examples, ensure autowire
and autoconfigure
are enabled.
app/config/services.yml
parameters:
PARAMETER_NAME: 'test'
services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
AppBundle\:
resource: '../../src/AppBundle/*'
exclude: '../../src/AppBundle/{DependencyInjection,Entity,Tests}'
# Additional Services Below Here
(depreciated as of Symfony 4.2 - removed in Syfmony 5.0+)
Using ContainerAwareCommand
works similarly to Parameter Injection, but instead of calling setParameterName()
. With autowiring
and autoconfig
enabled, Symfony will automatically inject the entire container using setContainer()
implemented from ContainerAwareInterface
.
src/AppBundle/Command/MyCommand.php
namespace AppBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class MyCommand extends ContainerAwareCommand
{
// ...
public function execute(InputInterface $input, OutputInterface $output)
{
dump($this->getContainer()->getParameter('PARAMETER_NAME'));
exit;
}
}
Requires Symfony 4.1+
To inject the ParameterBag with Dependency Injection when autowire
is enabled, add ParameterBagInterface
to the service constructor.
src/AppBundle/Command/MyCommand.php
namespace AppBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class MyCommand extends Command
{
private $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
parent::__construct();
}
// ...
public function execute(InputInterface $input, OutputInterface $output)
{
dump($this->parameterBag->get('PARAMETER_NAME'));
exit;
}
public static function getDefaultName()
{
return 'app:my_command';
}
}