Andreas Frömer
Posted on June 3, 2020
I would assume that everyone has fiddled around with symfony/console
right? If not, you should probably check it out here. It is pretty easy to use and understand.
One thing I had problems today is: How do you add a required argument for every command that is added to the console application?
I came up with 3 solutions:
- Adding a
BaseCommand
class which every command added has toextend
from - Add a required argument to the
Console\Application
- Add a required argument for each
Console\Command
added to theConsole\Application
TLDR;
Like President Schwarzenegger used to say in the Simpson Movie: "I pick number three".
This way for me is most robust change as you don't need to alter any command and every new command that will be added, will receive the required argument.
Just as a side note: I used to pick the first approach :)
Adding a BaseCommand
class which every command added has to extend
from
This is pretty straight forward. You create a new BaseCommand
class and add your required argument into the configure()
method.
<?php
use Symfony\Component\Console\Command\Command;
class BaseCommand extends Command
{
public function configure(): void
{
$this->addArgument(
'name',
InputArgument::REQUIRED,
'description'
);
}
}
But, what this would require is you have to call parent::configure()
in every command so that the argument is there, if not. Well its not.
Add a required argument to the Console\Application
This was the second approach I found while searching for a solution.
Sadly, every solution I found was adding a new optional argument to the definition, which is not what I needed, you might need to "fiddle" around with the setArguments()
of the InputDefinition
of an application.
You can do this inside you bootstrap file, whery you load the application.
$app = new Application();
$appDefinition = $app->getDefinition();
$appDefininition->setArguments(
array_merge([$requiredArgument], $appDefinition->getArguments())
);
But this is kind of out of scope where you want to define it.
So you can create your custom application class and do it there:
<?php
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputDefinition;
class CustomApplication extends Application
{
protected function getDefaultInputDefinition(): InputDefinition
{
$definition = parent::getDefaultInputDefinition();
$definition->setArguments(
array_merge([$requiredArgument], $definition->getArguments())
);
return $definition;
}
}
Downside on this: You have a require argument for every command of your application even with the HelpCommand
or ListCommand
. So you can't run you application by simply running bin/console
(if that is you entrypoint). You would need to pass the required argument everytime.
Add a required argument for each Console\Command
added to the Console\Application
The solution I choose, was to add this argument for each command added to the application.
Some of you might think: Wait a second, what abount HelpCommand
and ListCommand
you mentioned before?
Yes you are right, every command, except commands from symfony/console
namespace :)
So this is my solution: Creating my CustomApplication
and overwriting the add(Command $command)
adding my required argument to every added command to my application.
<?php
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Command\Command;
class ConsoleApplication extends Application
{
public function add(Command $command)
{
if (strpos(get_class($command), 'Symfony\Component\Console') === 0) {
return parent::add($command);
}
$commandDefinition = $command->getDefinition();
$commandDefinition->setArguments(
array_merge([$requiredArgument], $commandDefinition->getArguments())
);
return parent::add($command);
}
}
There you have it. Every command will get your required argument. Also this will be the first argument in every command. So even if you have an optional argument configured, there won't be a problem with that.
Hope that will help some of you solving the same problem I had :)
If you have another clever solution, let me know!
Posted on June 3, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.