Reputation: 1154
I'm developing a pretty simple Symfony console application. It has just one command with one argument, and a few options.
I followed this guide to create an extension of the Application
class.
This is the normal usage for the app, and it works fine:
php application <argument>
This also works fine (argument with options):
php application.php <argument> --some-option
If someone runs php application.php
without any arguments or options, I want it to run as though the user had run php application.php --help
.
I do have a working solution but it isn't optimal and is perhaps slightly brittle. In my extended Application
class, I overrode the run()
method as follows:
/**
* Override parent method so that --help options is used when app is called with no arguments or options
*
* @param InputInterface|null $input
* @param OutputInterface|null $output
* @return int
* @throws \Exception
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
if ($input === null) {
if (count($_SERVER["argv"]) <= 1) {
$args = array_merge($_SERVER["argv"], ["--help"]);
$input = new ArgvInput($args);
}
}
return parent::run($input, $output);
}
By default, Application::run()
is called with a null InputInterface
, so here I figured I could just check the raw value of the arguments and forcefully add a help option to pass to the parent method.
Is there a better way to achieve this?
Upvotes: 11
Views: 2892
Reputation: 1324
See the Symfony DescriptorHelper
on GitHub
use Symfony\Component\Console\Helper\DescriptorHelper;
public function handle(): int
{
/**
* @var array<string, mixed> $options
*/
$options = $this->options();
$helper = new DescriptorHelper();
$helper->describe($this->output, $this, [
// 'format' => $this->input->getOption('format'),
'format' => 'txt', // txt|xml|json|md|rst
// 'raw_text' => $this->input->getOption('raw'),
// 'raw_text' => false,
]);
txt
(default) or xml|json|md|rst
This is how the Symfony HelpCommand renders help for other commands. We just pass the class instance to $helper->describe($this->output, $this, [])
instead of another command.
There are around 100 methods available on the command class instance. It appears that public function help()
is not defined, so this could be put into a separate method.
use Symfony\Component\Console\Helper\DescriptorHelper;
/**
* Get the underlying Symfony output implementation.
*
* @return \Symfony\Component\Console\Output\OutputInterface
*/
abstract public function getOutput();
/**
* @param string $format txt|xml|json|md|rst
*/
public function help(string $format = 'txt', bool $raw_text = false): void
{
$helper = new DescriptorHelper();
$helper->describe($this->getOutput(), $this, [
'format' => $format,
'raw_text' => $raw_text,
]);
}
This will allow you to call help in your command as needed.
Display standard CLI help:
$this->help();
Display the help as JSON:
$this->help('json');
Upvotes: 0
Reputation: 13167
To do a specific action depending on command, you can use an EventListener
which is called when the onConsoleCommand
is fired.
The listener class should work as follows :
<?php
namespace AppBundle\EventListener;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Command\HelpCommand;
class ConsoleEventListener
{
public function onConsoleCommand(ConsoleCommandEvent $event)
{
$application = $event->getCommand()->getApplication();
$inputDefinition = $application->getDefinition();
if ($inputDefinition->getArgumentCount() < 2) {
$help = new HelpCommand();
$help->setCommand($event->getCommand());
return $help->run($event->getInput(), $event->getOutput());
}
}
}
The service declaration :
services:
# ...
app.console_event_listener:
class: AppBundle\EventListener\ConsoleEventListener
tags:
- { name: kernel.event_listener, event: console.command, method: onConsoleCommand }
Upvotes: 3
Reputation: 1154
I managed to work out a solution which didn't involve touching the Application
class at all. To call the help command from within another command:
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int
* @throws \Symfony\Component\Console\Exception\ExceptionInterface
*/
protected function outputHelp(InputInterface $input, OutputInterface $output)
{
$help = new HelpCommand();
$help->setCommand($this);
return $help->run($input, $output);
}
Upvotes: 11