Skip to content

[Console] Document invokable command #20932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: 7.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions components/console/changing_default_command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,14 @@ name to the ``setDefaultCommand()`` method::

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(name: 'hello:world')]
#[AsCommand(name: 'hello:world', description: 'Outputs "Hello World"')]
class HelloWorldCommand extends Command
{
protected function configure(): void
public function __invoke(SymfonyStyle $io): int
{
$this->setDescription('Outputs "Hello World"');
}

protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('Hello World');
$io->writeln('Hello World');

return Command::SUCCESS;
}
Expand Down
28 changes: 12 additions & 16 deletions components/console/events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,36 +209,32 @@ method::
for these constants to be available.

If you use the Console component inside a Symfony application, commands can
handle signals themselves. To do so, implement the
:class:`Symfony\\Component\\Console\\Command\\SignalableCommandInterface` and subscribe to one or more signals::
handle signals themselves by subscribing to the :class:`Symfony\\Component\\Console\\Event\\ConsoleSignalEvent` event::

// src/Command/SomeCommand.php
// src/Command/MyCommand.php
namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Command\SignalableCommandInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

class SomeCommand extends Command implements SignalableCommandInterface
#[AsCommand(name: 'app:my-command')]
class MyCommand
{
// ...

public function getSubscribedSignals(): array
#[AsEventListener(ConsoleSignalEvent::class)]
public function handleSignal(ConsoleSignalEvent $event): void
{
// return here any of the constants defined by PCNTL extension
return [\SIGINT, \SIGTERM];
}

public function handleSignal(int $signal): int|false
{
if (\SIGINT === $signal) {
// set here any of the constants defined by PCNTL extension
if (in_array($event->getHandlingSignal(), [\SIGINT, \SIGTERM], true)) {
// ...
}

// ...

// return an integer to set the exit code, or
// set an integer exit code, or
// false to continue normal execution
return 0;
$event->setExitCode(0);
}
}

Expand Down
8 changes: 4 additions & 4 deletions components/console/helpers/cursor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ of the output:
// src/Command/MyCommand.php
namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Cursor;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class MyCommand extends Command
#[AsCommand(name: 'app:my-command')]
class MyCommand
{
// ...

public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(OutputInterface $output): int
{
// ...

Expand Down
9 changes: 4 additions & 5 deletions components/console/helpers/debug_formatter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ this:
.. image:: /_images/components/console/debug_formatter.png
:alt: Console output, with the first line showing "RUN Running figlet", followed by lines showing the output of the command prefixed with "OUT" and "RES Finished the command" as last line in the output.

Using the debug_formatter
Using the Debug Formatter
-------------------------

The formatter is included in the default helper set and you can get it by
calling :method:`Symfony\\Component\\Console\\Command\\Command::getHelper`::
The debug formatter helper can be instantiated directly as shown::

$debugFormatter = $this->getHelper('debug_formatter');
$debugFormatter = new DebugFormatterHelper();

The formatter accepts strings and returns a formatted string, which you then
It accepts strings and returns a formatted string, which you then
output to the console (or even log the information or do anything else).

All methods of this helper have an identifier as the first argument. This is a
Expand Down
12 changes: 4 additions & 8 deletions components/console/helpers/formatterhelper.rst
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
Formatter Helper
================

The Formatter helper provides functions to format the output with colors.
You can do more advanced things with this helper than you can in
:doc:`/console/coloring`.
The :class:`Symfony\\Component\\Console\\Helper\\FormatterHelper` helper provides
functions to format the output with colors. You can do more advanced things with
this helper than you can in :doc:`/console/coloring`::

The :class:`Symfony\\Component\\Console\\Helper\\FormatterHelper` is included
in the default helper set and you can get it by calling
:method:`Symfony\\Component\\Console\\Command\\Command::getHelper`::

$formatter = $this->getHelper('formatter');
$formatter = new FormatterHelper();

The methods return a string, which you'll usually render to the console by
passing it to the
Expand Down
2 changes: 1 addition & 1 deletion components/console/helpers/processhelper.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ a very verbose verbosity (e.g. ``-vv``)::

use Symfony\Component\Process\Process;

$helper = $this->getHelper('process');
$helper = new ProcessHelper();
$process = new Process(['figlet', 'Symfony']);

$helper->run($output, $process);
Expand Down
62 changes: 30 additions & 32 deletions components/console/helpers/questionhelper.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ Question Helper
===============

The :class:`Symfony\\Component\\Console\\Helper\\QuestionHelper` provides
functions to ask the user for more information. It is included in the default
helper set and you can get it by calling
:method:`Symfony\\Component\\Console\\Command\\Command::getHelper`::
functions to ask the user for more information::

$helper = $this->getHelper('question');
$helper = new QuestionHelper();

The Question Helper has a single method
:method:`Symfony\\Component\\Console\\Helper\\QuestionHelper::ask` that needs an
Expand All @@ -27,18 +25,18 @@ Suppose you want to confirm an action before actually executing it. Add
the following to your command::

// ...
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;

class YourCommand extends Command
#[AsCommand(name: 'app:my-command')]
class MyCommand
{
// ...

public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
$helper = $this->getHelper('question');
$helper = new QuestionHelper();
$question = new ConfirmationQuestion('Continue with this action?', false);

if (!$helper->ask($input, $output, $question)) {
Expand Down Expand Up @@ -91,7 +89,7 @@ if you want to know a bundle name, you can add this to your command::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
Expand Down Expand Up @@ -121,10 +119,10 @@ but ``red`` could be set instead (could be more explicit)::
use Symfony\Component\Console\Question\ChoiceQuestion;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();
$question = new ChoiceQuestion(
'Please select your favorite color (defaults to red)',
// choices can also be PHP objects that implement __toString() method
Expand Down Expand Up @@ -184,10 +182,10 @@ this use :method:`Symfony\\Component\\Console\\Question\\ChoiceQuestion::setMult
use Symfony\Component\Console\Question\ChoiceQuestion;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();
$question = new ChoiceQuestion(
'Please select your favorite colors (defaults to red and blue)',
['red', 'blue', 'yellow'],
Expand Down Expand Up @@ -218,10 +216,10 @@ will be autocompleted as the user types::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$bundles = ['AcmeDemoBundle', 'AcmeBlogBundle', 'AcmeStoreBundle'];
$question = new Question('Please enter the name of a bundle', 'FooBundle');
Expand All @@ -241,9 +239,9 @@ provide a callback function to dynamically generate suggestions::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

// This function is called whenever the input changes and new
// suggestions are needed.
Expand Down Expand Up @@ -282,10 +280,10 @@ You can also specify if you want to not trim the answer by setting it directly w
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('What is the name of the child?');
$question->setTrimmable(false);
Expand All @@ -308,10 +306,10 @@ the response to a question should allow multiline answers by passing ``true`` to
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('How do you solve world peace?');
$question->setMultiline(true);
Expand All @@ -335,10 +333,10 @@ convenient for passwords::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('What is the database password?');
$question->setHidden(true);
Expand Down Expand Up @@ -372,10 +370,10 @@ convenient for passwords::
use Symfony\Component\Console\Question\ChoiceQuestion;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();
QuestionHelper::disableStty();

// ...
Expand All @@ -396,10 +394,10 @@ method::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
$question->setNormalizer(function (string $value): string {
Expand Down Expand Up @@ -434,10 +432,10 @@ method::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('Please enter the name of the bundle', 'AcmeDemoBundle');
$question->setValidator(function (string $answer): string {
Expand Down Expand Up @@ -494,10 +492,10 @@ You can also use a validator with a hidden question::
use Symfony\Component\Console\Question\Question;

// ...
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = $this->getHelper('question');
$helper = new QuestionHelper();

$question = new Question('Please enter your password');
$question->setNormalizer(function (?string $value): string {
Expand Down
12 changes: 7 additions & 5 deletions components/console/helpers/table.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ features, use the ``Table`` console helper explained in this article.
To display a table, use :class:`Symfony\\Component\\Console\\Helper\\Table`,
set the headers, set the rows and then render the table::

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// ...

class SomeCommand extends Command
#[AsCommand(name: 'app:my-command')]
class MyCommand
{
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(OutputInterface $output): int
{
$table = new Table($output);
$table
Expand Down Expand Up @@ -472,9 +473,10 @@ The only requirement to append rows is that the table must be rendered inside a
use Symfony\Component\Console\Helper\Table;
// ...

class SomeCommand extends Command
#[AsCommand(name: 'app:my-command')]
class MyCommand
{
public function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(OutputInterface $output): int
{
$section = $output->section();
$table = new Table($section);
Expand Down
11 changes: 3 additions & 8 deletions components/console/helpers/tree.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,17 @@ inside your console command::
namespace App\Command;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\TreeHelper;
use Symfony\Component\Console\Helper\TreeNode;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(name: 'app:some-command', description: '...')]
class SomeCommand extends Command
#[AsCommand(name: 'app:my-command', description: '...')]
class MyCommand
{
// ...

protected function execute(InputInterface $input, OutputInterface $output): int
public function __invoke(SymfonyStyle $io): int
{
$io = new SymfonyStyle($input, $output);

$node = TreeNode::fromValues([
'config/',
'public/',
Expand Down
Loading
Loading