mirror of
https://github.com/symfony/symfony-docs.git
synced 2026-03-24 00:32:14 +01:00
minor #20932 [Console] Document invokable command (yceruto)
This PR was squashed before being merged into the 7.3 branch.
Discussion
----------
[Console] Document invokable command
Closes https://github.com/symfony/symfony-docs/issues/20553
- [x] Make invokable commands first-class citizen
- [ ] Move old command definition to a separate section
Pending docs to be updated:
- [ ] components/console/console_arguments.rst (full refactoring required)
- [x] components/console/helpers/questionhelper.rst (full refactoring required)
- [ ] console/input.rst (full refactoring required)
- [x] console.rst
Commits
-------
0546a2ce4 [Console] Document invokable command
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
// ...
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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)) {
|
||||
@@ -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');
|
||||
@@ -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
|
||||
@@ -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'],
|
||||
@@ -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');
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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();
|
||||
|
||||
// ...
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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/',
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
200
console.rst
200
console.rst
@@ -107,26 +107,25 @@ completion (by default, by pressing the Tab key).
|
||||
installation instructions for your shell. The Symfony CLI will provide
|
||||
completion for the ``console`` and ``composer`` commands.
|
||||
|
||||
.. _console_creating-command:
|
||||
|
||||
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. Use
|
||||
the ``#[AsCommand]`` attribute to auto-register it::
|
||||
|
||||
// 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,104 +146,54 @@ want a command to create a user::
|
||||
}
|
||||
}
|
||||
|
||||
Configuring the Command
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can optionally define a description, help message and the
|
||||
:doc:`input options and arguments </console/input>` by overriding the
|
||||
``configure()`` method::
|
||||
|
||||
// src/Command/CreateUserCommand.php
|
||||
|
||||
// ...
|
||||
class CreateUserCommand extends Command
|
||||
{
|
||||
// ...
|
||||
protected function configure(): void
|
||||
{
|
||||
$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...')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
.. tip::
|
||||
|
||||
Using the ``#[AsCommand]`` attribute to define a description instead of
|
||||
using the ``setDescription()`` method allows to get the command description without
|
||||
instantiating its class. This makes the ``php bin/console list`` command run
|
||||
much faster.
|
||||
|
||||
If you want to always run the ``list`` command fast, add the ``--short`` option
|
||||
to it (``php bin/console list --short``). This will avoid instantiating command
|
||||
classes, but it won't show any description for commands that use the
|
||||
``setDescription()`` method instead of the attribute to define the command
|
||||
description.
|
||||
|
||||
The ``configure()`` method is called automatically at the end of the command
|
||||
constructor. If your command defines its own constructor, set the properties
|
||||
first and then call to the parent constructor, to make those properties
|
||||
available in the ``configure()`` method::
|
||||
|
||||
// ...
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
|
||||
class CreateUserCommand extends Command
|
||||
{
|
||||
// ...
|
||||
|
||||
public function __construct(bool $requirePassword = false)
|
||||
{
|
||||
// best practices recommend to call the parent constructor first and
|
||||
// then set your own properties. That wouldn't work in this case
|
||||
// because configure() needs the properties set in this constructor
|
||||
$this->requirePassword = $requirePassword;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
// ...
|
||||
->addArgument('password', $this->requirePassword ? InputArgument::REQUIRED : InputArgument::OPTIONAL, 'User password')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
.. _console_registering-the-command:
|
||||
|
||||
Registering the Command
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can register the command by adding the ``AsCommand`` attribute to it::
|
||||
|
||||
// src/Command/CreateUserCommand.php
|
||||
namespace App\Command;
|
||||
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'app:create-user',
|
||||
description: 'Creates a new user.',
|
||||
hidden: false,
|
||||
aliases: ['app:add-user']
|
||||
)]
|
||||
class CreateUserCommand extends Command
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
If you can't use PHP attributes, register the command as a service and
|
||||
:doc:`tag it </service_container/tags>` with the ``console.command`` tag. If you're using the
|
||||
:ref:`default services.yaml configuration <service-container-services-load-example>`,
|
||||
this is already done for you, thanks to :ref:`autoconfiguration <services-autoconfigure>`.
|
||||
|
||||
You can also use ``#[AsCommand]`` to add a description and longer help text for the 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
|
||||
{
|
||||
public function __invoke(): int
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
Additionally, you can extend the :class:`Symfony\\Component\\Console\\Command\\Command` class to
|
||||
leverage advanced features like lifecycle hooks (e.g. :method:`Symfony\\Component\\Console\\Command\\Command::initialize` and
|
||||
and :method:`Symfony\\Component\\Console\\Command\\Command::interact`)::
|
||||
|
||||
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:create-user')]
|
||||
class CreateUserCommand extends Command
|
||||
{
|
||||
public function initialize(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
public function interact(InputInterface $input, OutputInterface $output): void
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
public function __invoke(): int
|
||||
{
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
Running the Command
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -255,16 +204,16 @@ After configuring and registering the command, you can run it in the terminal:
|
||||
$ php bin/console app:create-user
|
||||
|
||||
As you might expect, this command will do nothing as you didn't write any logic
|
||||
yet. Add your own logic inside the ``execute()`` method.
|
||||
yet. Add your own logic inside the ``__invoke()`` method.
|
||||
|
||||
Console Output
|
||||
--------------
|
||||
|
||||
The ``execute()`` method has access to the output stream to write messages to
|
||||
The ``__invoke()`` method has access to the output stream to write messages to
|
||||
the console::
|
||||
|
||||
// ...
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
public function __invoke(OutputInterface $output): int
|
||||
{
|
||||
// outputs multiple lines to the console (adding "\n" at the end of each line)
|
||||
$output->writeln([
|
||||
@@ -315,9 +264,10 @@ method, which returns an instance of
|
||||
// ...
|
||||
use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
|
||||
class MyCommand extends Command
|
||||
#[AsCommand(name: 'app:my-command')]
|
||||
class MyCommand
|
||||
{
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
public function __invoke(OutputInterface $output): int
|
||||
{
|
||||
if (!$output instanceof ConsoleOutputInterface) {
|
||||
throw new \LogicException('This command accepts only an instance of "ConsoleOutputInterface".');
|
||||
@@ -376,20 +326,12 @@ Console Input
|
||||
|
||||
Use input options or arguments to pass information to the command::
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Attribute\Argument;
|
||||
|
||||
// ...
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
// configure an argument
|
||||
->addArgument('username', InputArgument::REQUIRED, 'The username of the user.')
|
||||
// ...
|
||||
;
|
||||
}
|
||||
|
||||
// ...
|
||||
public function execute(InputInterface $input, OutputInterface $output): int
|
||||
// The #[Argument] attribute configures $username as a
|
||||
// required input argument and its value is automatically
|
||||
// passed to this parameter
|
||||
public function __invoke(#[Argument('The username of the user.')] string $username, OutputInterface $output): int
|
||||
{
|
||||
$output->writeln([
|
||||
'User Creator',
|
||||
@@ -397,8 +339,7 @@ Use input options or arguments to pass information to the command::
|
||||
'',
|
||||
]);
|
||||
|
||||
// retrieve the argument value using getArgument()
|
||||
$output->writeln('Username: '.$input->getArgument('username'));
|
||||
$output->writeln('Username: '.$username);
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
@@ -428,23 +369,22 @@ as a service, you can use normal dependency injection. Imagine you have a
|
||||
|
||||
// ...
|
||||
use App\Service\UserManager;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Attribute\Argument;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
|
||||
class CreateUserCommand extends Command
|
||||
#[AsCommand(name: 'app:create-user')]
|
||||
class CreateUserCommand
|
||||
{
|
||||
public function __construct(
|
||||
private UserManager $userManager,
|
||||
){
|
||||
parent::__construct();
|
||||
private UserManager $userManager
|
||||
) {
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
public function __invoke(#[Argument] string $username, OutputInterface $output): int
|
||||
{
|
||||
// ...
|
||||
|
||||
$this->userManager->create($input->getArgument('username'));
|
||||
$this->userManager->create($username);
|
||||
|
||||
$output->writeln('User successfully generated!');
|
||||
|
||||
@@ -472,7 +412,7 @@ command:
|
||||
Note that it will not be called when the command is run without interaction
|
||||
(e.g. when passing the ``--no-interaction`` global option flag).
|
||||
|
||||
:method:`Symfony\\Component\\Console\\Command\\Command::execute` *(required)*
|
||||
``__invoke()`` *(required)*
|
||||
This method is executed after ``interact()`` and ``initialize()``.
|
||||
It contains the logic you want the command to execute and it must
|
||||
return an integer which will be used as the command `exit status`_.
|
||||
|
||||
@@ -14,20 +14,18 @@ arguments and options you want to pass to the command. The command name must be
|
||||
the first argument.
|
||||
|
||||
Eventually, calling the ``doRun()`` method actually runs the command and returns
|
||||
the returned code from the command (return value from command ``execute()``
|
||||
the returned code from the command (return value from command ``__invoke()``
|
||||
method)::
|
||||
|
||||
// ...
|
||||
use Symfony\Component\Console\Command;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
// ...
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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, 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/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');
|
||||
|
||||
// ...
|
||||
@@ -454,19 +450,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);
|
||||
|
||||
// ...
|
||||
@@ -493,7 +487,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;
|
||||
@@ -501,16 +495,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);
|
||||
|
||||
// ...
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,23 +33,22 @@ 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\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
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(): int
|
||||
{
|
||||
$this->logger->debug('Some info');
|
||||
$this->logger->notice('Some more info');
|
||||
|
||||
@@ -14,7 +14,7 @@ Doctrine Bridge
|
||||
Command
|
||||
~~~~~~~
|
||||
|
||||
* :ref:`AsCommand <console_registering-the-command>`
|
||||
* :ref:`AsCommand <console_creating-command>`
|
||||
|
||||
Contracts
|
||||
~~~~~~~~~
|
||||
|
||||
18
routing.rst
18
routing.rst
@@ -2731,23 +2731,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');
|
||||
|
||||
@@ -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
|
||||
---------------------------
|
||||
|
||||
Reference in New Issue
Block a user