From a59a80c06237be6d17ad96eded72a4763f138ae5 Mon Sep 17 00:00:00 2001
From: Yonel Ceruto <yonel.ceruto@scnd.com>
Date: Thu, 1 May 2025 11:52:20 -0400
Subject: [PATCH 1/4] Document invokable command

---
 .../console/changing_default_command.rst      | 14 ++---
 components/console/events.rst                 | 26 ++++-----
 components/console/helpers/cursor.rst         |  8 +--
 components/console/helpers/questionhelper.rst |  8 +--
 components/console/helpers/table.rst          | 12 +++--
 components/console/helpers/tree.rst           | 11 ++--
 components/console/logger.rst                 |  5 +-
 components/console/single_command_tool.rst    | 11 ++--
 components/process.rst                        |  9 +++-
 console.rst                                   | 32 ++++++-----
 console/calling_commands.rst                  |  9 ++--
 console/commands_as_services.rst              | 19 ++-----
 console/hide_commands.rst                     |  3 +-
 console/lockable_trait.rst                    | 15 +++---
 console/style.rst                             | 53 ++++++++-----------
 console/verbosity.rst                         | 13 ++---
 logging/monolog_console.rst                   | 10 ++--
 routing.rst                                   | 18 +++----
 scheduler.rst                                 |  6 ++-
 19 files changed, 124 insertions(+), 158 deletions(-)

diff --git a/components/console/changing_default_command.rst b/components/console/changing_default_command.rst
index c69995ea395..2195bbd2697 100644
--- a/components/console/changing_default_command.rst
+++ b/components/console/changing_default_command.rst
@@ -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;
         }
diff --git a/components/console/events.rst b/components/console/events.rst
index e550025b7dd..4fbda573462 100644
--- a/components/console/events.rst
+++ b/components/console/events.rst
@@ -209,28 +209,24 @@ 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. To do so, subscribe to :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)) {
                 // ...
             }
 
@@ -238,7 +234,7 @@ handle signals themselves. To do so, implement the
 
             // return an integer to set the exit code, or
             // false to continue normal execution
-            return 0;
+            $event->setExitCode(0);
         }
     }
 
diff --git a/components/console/helpers/cursor.rst b/components/console/helpers/cursor.rst
index c5cab6c6d0b..ceca608577d 100644
--- a/components/console/helpers/cursor.rst
+++ b/components/console/helpers/cursor.rst
@@ -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: 'my-command')]
+    class MyCommand
     {
         // ...
 
-        public function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(OutputInterface $output): int
         {
             // ...
 
diff --git a/components/console/helpers/questionhelper.rst b/components/console/helpers/questionhelper.rst
index c7e064b16ca..fc450d07b55 100644
--- a/components/console/helpers/questionhelper.rst
+++ b/components/console/helpers/questionhelper.rst
@@ -27,16 +27,16 @@ 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');
             $question = new ConfirmationQuestion('Continue with this action?', false);
diff --git a/components/console/helpers/table.rst b/components/console/helpers/table.rst
index 9d6fdb0ee61..d05e5c981e6 100644
--- a/components/console/helpers/table.rst
+++ b/components/console/helpers/table.rst
@@ -22,15 +22,16 @@ When building a console application it may be useful to display tabular data:
 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
@@ -445,9 +446,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);
diff --git a/components/console/helpers/tree.rst b/components/console/helpers/tree.rst
index 1161d00e942..7e9149d7d33 100644
--- a/components/console/helpers/tree.rst
+++ b/components/console/helpers/tree.rst
@@ -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
+        protected function execute(SymfonyStyle $io): int
         {
-            $io = new SymfonyStyle($input, $output);
-
             $node = TreeNode::fromValues([
                 'config/',
                 'public/',
diff --git a/components/console/logger.rst b/components/console/logger.rst
index c3d5c447a89..cc182821a0a 100644
--- a/components/console/logger.rst
+++ b/components/console/logger.rst
@@ -34,7 +34,6 @@ You can rely on the logger to use this dependency inside a command::
     use Acme\MyDependency;
     use Symfony\Component\Console\Attribute\AsCommand;
     use Symfony\Component\Console\Command\Command;
-    use Symfony\Component\Console\Input\InputInterface;
     use Symfony\Component\Console\Logger\ConsoleLogger;
     use Symfony\Component\Console\Output\OutputInterface;
 
@@ -42,9 +41,9 @@ You can rely on the logger to use this dependency inside a command::
         name: 'my:command',
         description: 'Use an external dependency requiring a PSR-3 logger'
     )]
-    class MyCommand extends Command
+    class MyCommand
     {
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(OutputInterface $output): int
         {
             $logger = new ConsoleLogger($output);
 
diff --git a/components/console/single_command_tool.rst b/components/console/single_command_tool.rst
index 97cb09bf030..9c6b06537e2 100644
--- a/components/console/single_command_tool.rst
+++ b/components/console/single_command_tool.rst
@@ -9,19 +9,18 @@ it is possible to remove this need by declaring a single command application::
     <?php
     require __DIR__.'/vendor/autoload.php';
 
-    use Symfony\Component\Console\Input\InputArgument;
-    use Symfony\Component\Console\Input\InputInterface;
-    use Symfony\Component\Console\Input\InputOption;
+    use Symfony\Component\Console\Attribute\Argument;
+    use Symfony\Component\Console\Attribute\Option;
     use Symfony\Component\Console\Output\OutputInterface;
     use Symfony\Component\Console\SingleCommandApplication;
 
     (new SingleCommandApplication())
         ->setName('My Super Command') // Optional
         ->setVersion('1.0.0') // Optional
-        ->addArgument('foo', InputArgument::OPTIONAL, 'The directory')
-        ->addOption('bar', null, InputOption::VALUE_REQUIRED)
-        ->setCode(function (InputInterface $input, OutputInterface $output): int {
+        ->setCode(function (OutputInterface $output, #[Argument] string $foo = 'The directory', #[Option] string $bar = ''): int {
             // output arguments and options
+
+            return 0;
         })
         ->run();
 
diff --git a/components/process.rst b/components/process.rst
index 7552537e82e..9c25c931510 100644
--- a/components/process.rst
+++ b/components/process.rst
@@ -430,11 +430,14 @@ However, if you run the command via the Symfony ``Process`` class, PHP will use
 the settings defined in the ``php.ini`` file. You can solve this issue by using
 the :class:`Symfony\\Component\\Process\\PhpSubprocess` class to run the command::
 
+    use Symfony\Component\Console\Attribute\AsCommand;
+    use Symfony\Component\Console\Style\SymfonyStyle;
     use Symfony\Component\Process\Process;
 
-    class MyCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
             // the memory_limit (and any other config option) of this command is
             // the one defined in php.ini instead of the new values (optionally)
@@ -444,6 +447,8 @@ the :class:`Symfony\\Component\\Process\\PhpSubprocess` class to run the command
             // the memory_limit (and any other config option) of this command takes
             // into account the values (optionally) passed via the '-d' command option
             $childProcess = new PhpSubprocess(['bin/console', 'cache:pool:prune']);
+
+            return 0;
         }
     }
 
diff --git a/console.rst b/console.rst
index 24fab9885da..46c03e39b95 100644
--- a/console.rst
+++ b/console.rst
@@ -110,23 +110,19 @@ completion (by default, by pressing the Tab key).
 Creating a Command
 ------------------
 
-Commands are defined in classes extending
-:class:`Symfony\\Component\\Console\\Command\\Command`. For example, you may
-want a command to create a user::
+Commands are defined in classes, for example, you may want a command to create a user::
 
     // src/Command/CreateUserCommand.php
     namespace App\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;
 
     // the name of the command is what users type after "php bin/console"
     #[AsCommand(name: 'app:create-user')]
-    class CreateUserCommand extends Command
+    class CreateUserCommand
     {
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(): int
         {
             // ... put here the code to create the user
 
@@ -147,6 +143,10 @@ want a command to create a user::
         }
     }
 
+Additionally, can extend the :class:`Symfony\\Component\\Console\\Command\\Command` class to
+leverage advanced features like lifecycle hooks: :method:`Symfony\\Component\\Console\\Command\\Command::initialize`,
+:method:`Symfony\\Component\\Console\\Command\\Command::interact`, and built-in helpers.
+
 Configuring the Command
 ~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -156,18 +156,16 @@ You can optionally define a description, help message and the
 
     // src/Command/CreateUserCommand.php
 
-    // ...
-    class CreateUserCommand extends Command
+    #[AsCommand(
+        name: 'app:create-user',
+        description: 'Creates a new user.', // the command description shown when running "php bin/console list"
+        help: 'This command allows you to create a user...', // the command help shown when running the command with the "--help" option
+    )]
+    class CreateUserCommand
     {
-        // ...
-        protected function configure(): void
+        public function __invoke(): int
         {
-            $this
-                // the command description shown when running "php bin/console list"
-                ->setDescription('Creates a new user.')
-                // the command help shown when running the command with the "--help" option
-                ->setHelp('This command allows you to create a user...')
-            ;
+            // ...
         }
     }
 
diff --git a/console/calling_commands.rst b/console/calling_commands.rst
index dd1f0b12ff9..b2cfa36c0c8 100644
--- a/console/calling_commands.rst
+++ b/console/calling_commands.rst
@@ -18,16 +18,15 @@ the returned code from the command (return value from command ``execute()``
 method)::
 
     // ...
+    use Symfony\Component\Console\Attribute\AsCommand;
     use Symfony\Component\Console\Command;
     use Symfony\Component\Console\Input\ArrayInput;
-    use Symfony\Component\Console\Input\InputInterface;
     use Symfony\Component\Console\Output\OutputInterface;
 
-    class CreateUserCommand extends Command
+    #[AsCommand(name: 'app:create-user')]
+    class CreateUserCommand
     {
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(OutputInterface $output): int
         {
             $greetInput = new ArrayInput([
                 // the command name is passed as first argument
diff --git a/console/commands_as_services.rst b/console/commands_as_services.rst
index 1393879a1df..ed5b99f9cb4 100644
--- a/console/commands_as_services.rst
+++ b/console/commands_as_services.rst
@@ -16,27 +16,16 @@ For example, suppose you want to log something from within your command::
 
     use Psr\Log\LoggerInterface;
     use Symfony\Component\Console\Attribute\AsCommand;
-    use Symfony\Component\Console\Command\Command;
-    use Symfony\Component\Console\Input\InputInterface;
-    use Symfony\Component\Console\Output\OutputInterface;
 
-    #[AsCommand(name: 'app:sunshine')]
-    class SunshineCommand extends Command
+    #[AsCommand(name: 'app:sunshine', description: 'Good morning!')]
+    class SunshineCommand
     {
         public function __construct(
             private LoggerInterface $logger,
         ) {
-            // you *must* call the parent constructor
-            parent::__construct();
-        }
-
-        protected function configure(): void
-        {
-            $this
-                ->setDescription('Good morning!');
         }
 
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(): int
         {
             $this->logger->info('Waking up the sun');
             // ...
@@ -70,7 +59,7 @@ To make your command lazily loaded, either define its name using the PHP
     // ...
 
     #[AsCommand(name: 'app:sunshine')]
-    class SunshineCommand extends Command
+    class SunshineCommand
     {
         // ...
     }
diff --git a/console/hide_commands.rst b/console/hide_commands.rst
index 44a69d09289..4ab9d3a6dad 100644
--- a/console/hide_commands.rst
+++ b/console/hide_commands.rst
@@ -15,10 +15,9 @@ the ``hidden`` property of the ``AsCommand`` attribute::
     namespace App\Command;
 
     use Symfony\Component\Console\Attribute\AsCommand;
-    use Symfony\Component\Console\Command\Command;
 
     #[AsCommand(name: 'app:legacy', hidden: true)]
-    class LegacyCommand extends Command
+    class LegacyCommand
     {
         // ...
     }
diff --git a/console/lockable_trait.rst b/console/lockable_trait.rst
index 0f4a4900e17..2a4fd64ffaf 100644
--- a/console/lockable_trait.rst
+++ b/console/lockable_trait.rst
@@ -13,19 +13,17 @@ that adds two convenient methods to lock and release commands::
     // ...
     use Symfony\Component\Console\Command\Command;
     use Symfony\Component\Console\Command\LockableTrait;
-    use Symfony\Component\Console\Input\InputInterface;
-    use Symfony\Component\Console\Output\OutputInterface;
+    use Symfony\Component\Console\Style\SymfonyStyle;
 
-    class UpdateContentsCommand extends Command
+    #[AsCommand(name: 'contents:update')]
+    class UpdateContentsCommand
     {
         use LockableTrait;
 
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
             if (!$this->lock()) {
-                $output->writeln('The command is already running in another process.');
+                $io->writeln('The command is already running in another process.');
 
                 return Command::SUCCESS;
             }
@@ -52,7 +50,8 @@ a ``$lockFactory`` property with your own lock factory::
     use Symfony\Component\Console\Command\LockableTrait;
     use Symfony\Component\Lock\LockFactory;
 
-    class UpdateContentsCommand extends Command
+    #[AsCommand(name: 'contents:update')]
+    class UpdateContentsCommand
     {
         use LockableTrait;
 
diff --git a/console/style.rst b/console/style.rst
index e1e5df38ffe..e05ad5d771d 100644
--- a/console/style.rst
+++ b/console/style.rst
@@ -7,18 +7,18 @@ questions to the user involves a lot of repetitive code.
 
 Consider for example the code used to display the title of the following command::
 
-    // src/Command/GreetCommand.php
+    // src/Command/MyCommand.php
     namespace App\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;
 
-    class GreetCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(InputInterface $input, OutputInterface $output): int
         {
             $output->writeln([
                 '<info>Lorem Ipsum Dolor Sit Amet</>',
@@ -42,26 +42,22 @@ which allow to create *semantic* commands and forget about their styling.
 Basic Usage
 -----------
 
-In your command, instantiate the :class:`Symfony\\Component\\Console\\Style\\SymfonyStyle`
-class and pass the ``$input`` and ``$output`` variables as its arguments. Then,
-you can start using any of its helpers, such as ``title()``, which displays the
-title of the command::
+In your `__invoke` method, type the :class:`Symfony\\Component\\Console\\Style\\SymfonyStyle`
+argument. Then, you can start using any of its helpers, such as ``title()``, which
+displays the title of the command::
 
-    // src/Command/GreetCommand.php
+    // src/Command/MyCommand.php
     namespace App\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\Style\SymfonyStyle;
 
-    class GreetCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
-            $io = new SymfonyStyle($input, $output);
             $io->title('Lorem Ipsum Dolor Sit Amet');
 
             // ...
@@ -448,19 +444,17 @@ long they are. This is done to enable clickable URLs in terminals that support t
 
 If you prefer to wrap all contents, including URLs, use this method::
 
-    // src/Command/GreetCommand.php
+    // src/Command/MyCommand.php
     namespace App\Command;
 
     // ...
     use Symfony\Component\Console\Style\SymfonyStyle;
 
-    class GreetCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
-            $io = new SymfonyStyle($input, $output);
             $io->getOutputWrapper()->setAllowCutUrls(true);
 
             // ...
@@ -487,7 +481,7 @@ Then, instantiate this custom class instead of the default ``SymfonyStyle`` in
 your commands. Thanks to the ``StyleInterface`` you won't need to change the code
 of your commands to change their appearance::
 
-    // src/Command/GreetCommand.php
+    // src/Command/MyCommand.php
     namespace App\Console;
 
     use App\Console\CustomStyle;
@@ -495,16 +489,11 @@ of your commands to change their appearance::
     use Symfony\Component\Console\Input\InputInterface;
     use Symfony\Component\Console\Output\OutputInterface;
 
-    class GreetCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        // ...
-
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(InputInterface $input, OutputInterface $output): int
         {
-            // Before
-            $io = new SymfonyStyle($input, $output);
-
-            // After
             $io = new CustomStyle($input, $output);
 
             // ...
diff --git a/console/verbosity.rst b/console/verbosity.rst
index 9910dca0c3d..cbbb1663895 100644
--- a/console/verbosity.rst
+++ b/console/verbosity.rst
@@ -49,21 +49,22 @@ It is possible to print a message in a command for only a specific verbosity
 level. For example::
 
     // ...
+    use Symfony\Component\Console\Attribute\Argument;
+    use Symfony\Component\Console\Attribute\AsCommand;
     use Symfony\Component\Console\Command\Command;
     use Symfony\Component\Console\Input\InputInterface;
     use Symfony\Component\Console\Output\OutputInterface;
 
-    class CreateUserCommand extends Command
+    #[AsCommand(name: 'app:create-user')]
+    class CreateUserCommand
     {
-        // ...
-
-        public function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(OutputInterface $output, #[Argument] string $username, #[Argument] string $password): int
         {
             $user = new User(...);
 
             $output->writeln([
-                'Username: '.$input->getArgument('username'),
-                'Password: '.$input->getArgument('password'),
+                'Username: '.$username,
+                'Password: '.$password,
             ]);
 
             // available methods: ->isSilent(), ->isQuiet(), ->isVerbose(), ->isVeryVerbose(), ->isDebug()
diff --git a/logging/monolog_console.rst b/logging/monolog_console.rst
index 67bf0f5acae..d6b8e2f6529 100644
--- a/logging/monolog_console.rst
+++ b/logging/monolog_console.rst
@@ -38,19 +38,19 @@ The example above could then be rewritten as::
     namespace App\Command;
 
     use Psr\Log\LoggerInterface;
+    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;
 
-    class YourCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
         public function __construct(
             private LoggerInterface $logger,
         ) {
-            parent::__construct();
         }
 
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
             $this->logger->debug('Some info');
             $this->logger->notice('Some more info');
diff --git a/routing.rst b/routing.rst
index 663e8518504..47e8ab32384 100644
--- a/routing.rst
+++ b/routing.rst
@@ -2484,23 +2484,23 @@ The solution is to configure the ``default_uri`` option to define the
 
 Now you'll get the expected results when generating URLs in your commands::
 
-    // src/Command/SomeCommand.php
+    // src/Command/MyCommand.php
     namespace App\Command;
 
-    use Symfony\Component\Console\Command\Command;
-    use Symfony\Component\Console\Input\InputInterface;
-    use Symfony\Component\Console\Output\OutputInterface;
+    use Symfony\Component\Console\Attribute\AsCommand;
+    use Symfony\Component\Console\Style\SymfonyStyle;
     use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
     // ...
 
-    class SomeCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
     {
-        public function __construct(private UrlGeneratorInterface $urlGenerator)
-        {
-            parent::__construct();
+        public function __construct(
+            private UrlGeneratorInterface $urlGenerator,
+        ) {
         }
 
-        protected function execute(InputInterface $input, OutputInterface $output): int
+        public function __invoke(SymfonyStyle $io): int
         {
             // generate a URL with no route arguments
             $signUpPage = $this->urlGenerator->generate('sign_up');
diff --git a/scheduler.rst b/scheduler.rst
index 765f60e156a..66eb77445b9 100644
--- a/scheduler.rst
+++ b/scheduler.rst
@@ -478,7 +478,8 @@ The attribute takes more parameters to customize the trigger::
     // when applying this attribute to a Symfony console command, you can pass
     // arguments and options to the command using the 'arguments' option:
     #[AsCronTask('0 0 * * *', arguments: 'some_argument --some-option --another-option=some_value')]
-    class MyCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
 
 .. _scheduler-attributes-periodic-task:
 
@@ -527,7 +528,8 @@ The ``#[AsPeriodicTask]`` attribute takes many parameters to customize the trigg
     // when applying this attribute to a Symfony console command, you can pass
     // arguments and options to the command using the 'arguments' option:
     #[AsPeriodicTask(frequency: '1 day', arguments: 'some_argument --some-option --another-option=some_value')]
-    class MyCommand extends Command
+    #[AsCommand(name: 'app:my-command')]
+    class MyCommand
 
 Managing Scheduled Messages
 ---------------------------

From 4a417f14e3ef4916250fdf357be7b0658f69a13b Mon Sep 17 00:00:00 2001
From: Yonel Ceruto <yonel.ceruto@scnd.com>
Date: Fri, 2 May 2025 12:59:31 -0400
Subject: [PATCH 2/4] Antoine's Review

---
 components/console/helpers/tree.rst | 2 +-
 console/style.rst                   | 4 ++--
 logging/monolog_console.rst         | 8 +++-----
 3 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/components/console/helpers/tree.rst b/components/console/helpers/tree.rst
index 7e9149d7d33..b3d773a27fd 100644
--- a/components/console/helpers/tree.rst
+++ b/components/console/helpers/tree.rst
@@ -35,7 +35,7 @@ inside your console command::
     {
         // ...
 
-        protected function execute(SymfonyStyle $io): int
+        public function __invoke(SymfonyStyle $io): int
         {
             $node = TreeNode::fromValues([
                 'config/',
diff --git a/console/style.rst b/console/style.rst
index e05ad5d771d..59a4d540c4e 100644
--- a/console/style.rst
+++ b/console/style.rst
@@ -42,8 +42,8 @@ which allow to create *semantic* commands and forget about their styling.
 Basic Usage
 -----------
 
-In your `__invoke` method, type the :class:`Symfony\\Component\\Console\\Style\\SymfonyStyle`
-argument. Then, you can start using any of its helpers, such as ``title()``, which
+In your `__invoke` method, add an argument of type :class:`Symfony\\Component\\Console\\Style\\SymfonyStyle`.
+Then, you can start using any of its helpers, such as ``title()``, which
 displays the title of the command::
 
     // src/Command/MyCommand.php
diff --git a/logging/monolog_console.rst b/logging/monolog_console.rst
index d6b8e2f6529..4d007abe854 100644
--- a/logging/monolog_console.rst
+++ b/logging/monolog_console.rst
@@ -10,10 +10,9 @@ When a lot of logging has to happen, it's cumbersome to print information
 depending on the verbosity settings (``-v``, ``-vv``, ``-vvv``) because the
 calls need to be wrapped in conditions. For example::
 
-    use Symfony\Component\Console\Input\InputInterface;
     use Symfony\Component\Console\Output\OutputInterface;
 
-    protected function execute(InputInterface $input, OutputInterface $output): int
+    public function __invoke(OutputInterface $output): int
     {
         if ($output->isDebug()) {
             $output->writeln('Some info');
@@ -34,13 +33,12 @@ the current log level and the console verbosity.
 
 The example above could then be rewritten as::
 
-    // src/Command/YourCommand.php
+    // src/Command/MyCommand.php
     namespace App\Command;
 
     use Psr\Log\LoggerInterface;
     use Symfony\Component\Console\Attribute\AsCommand;
     use Symfony\Component\Console\Command\Command;
-    use Symfony\Component\Console\Style\SymfonyStyle;
 
     #[AsCommand(name: 'app:my-command')]
     class MyCommand
@@ -50,7 +48,7 @@ The example above could then be rewritten as::
         ) {
         }
 
-        public function __invoke(SymfonyStyle $io): int
+        public function __invoke(): int
         {
             $this->logger->debug('Some info');
             $this->logger->notice('Some more info');

From 236dd82a701ee2dbccf1213fff9b0ef987d667a2 Mon Sep 17 00:00:00 2001
From: Yonel Ceruto <yonel.ceruto@scnd.com>
Date: Mon, 5 May 2025 13:58:40 -0400
Subject: [PATCH 3/4] Oskar's Review

---
 components/console/events.rst | 4 ++--
 console.rst                   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/components/console/events.rst b/components/console/events.rst
index 4fbda573462..699ba444747 100644
--- a/components/console/events.rst
+++ b/components/console/events.rst
@@ -209,7 +209,7 @@ 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, subscribe to :class:`Symfony\\Component\\Console\\Event\\ConsoleSignalEvent` event::
+handle signals themselves by subscribing to the :class:`Symfony\\Component\\Console\\Event\\ConsoleSignalEvent` event::
 
     // src/Command/MyCommand.php
     namespace App\Command;
@@ -232,7 +232,7 @@ handle signals themselves. To do so, subscribe to :class:`Symfony\\Component\\Co
 
             // ...
 
-            // return an integer to set the exit code, or
+            // set an integer exit code, or
             // false to continue normal execution
             $event->setExitCode(0);
         }
diff --git a/console.rst b/console.rst
index 46c03e39b95..84ca4c1a931 100644
--- a/console.rst
+++ b/console.rst
@@ -143,7 +143,7 @@ Commands are defined in classes, for example, you may want a command to create a
         }
     }
 
-Additionally, can extend the :class:`Symfony\\Component\\Console\\Command\\Command` class to
+Additionally, you can extend the :class:`Symfony\\Component\\Console\\Command\\Command` class to
 leverage advanced features like lifecycle hooks: :method:`Symfony\\Component\\Console\\Command\\Command::initialize`,
 :method:`Symfony\\Component\\Console\\Command\\Command::interact`, and built-in helpers.
 

From 1a9a5d79f8aaf241916a3aaa0f0519fc2732aea7 Mon Sep 17 00:00:00 2001
From: Yonel Ceruto <yonel.ceruto@scnd.com>
Date: Mon, 5 May 2025 16:42:13 -0400
Subject: [PATCH 4/4] Antoine's Review

---
 components/console/helpers/cursor.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/components/console/helpers/cursor.rst b/components/console/helpers/cursor.rst
index ceca608577d..63045f178ad 100644
--- a/components/console/helpers/cursor.rst
+++ b/components/console/helpers/cursor.rst
@@ -17,7 +17,7 @@ of the output:
     use Symfony\Component\Console\Cursor;
     use Symfony\Component\Console\Output\OutputInterface;
 
-    #[AsCommand(name: 'my-command')]
+    #[AsCommand(name: 'app:my-command')]
     class MyCommand
     {
         // ...