Commands With Arguments and Options
Commands With Arguments and Options
~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
A hardwired command rarely suffices – this chapter makes our overdue-tasks command CONFIGURABLE: a project filter as an argument, a "count only" mode as an option.
Arguments vs. options: the difference
| Type | Properties |
|---|---|
| Argument | REQUIRED (unless a default is set), POSITIONAL – app:command value. |
| Option | ALWAYS optional, referenced BY NAME, order-independent – app:command --option=value or --option as a plain on/off switch. |
Adding an argument: project filter
use Symfony\Component\Console\Attribute\Argument;
use App\Repository\ProjectRepository;
// ... class attribute and constructor as in chapter 39, ProjectRepository additionally injected ...
protected function execute(
InputInterface $input,
OutputInterface $output,
#[Argument(description: 'Optional project ID to filter by')]
?int $projectId = null,
): int {
$io = new SymfonyStyle($input, $output);
if ($projectId !== null) {
$project = $this->projectRepository->find($projectId);
if ($project === null) {
$io->error(sprintf('Project with ID %d not found.', $projectId));
return Command::FAILURE;
}
}
// ... rest of the logic as in chapter 39 ...
}The MODERN syntax (Symfony 7.1+): #[Argument] DIRECTLY on the method parameter, with standard PHP typing (?int for optional). Symfony handles parsing and type conversion AUTOMATICALLY – no manual $input->getArgument('project-id') plus (int) cast needed anymore, as the older syntax required.
Adding an option: count only
use Symfony\Component\Console\Attribute\Option;
protected function execute(
InputInterface $input,
OutputInterface $output,
#[Argument(description: 'Optional project ID to filter by')]
?int $projectId = null,
#[Option(description: 'Only output the count, no details')]
bool $countOnly = false,
): int {
// ...
if ($countOnly) {
$io->writeln((string) count($tasks));
return Command::SUCCESS;
}
// ... normal output as before ...
}Running the command with arguments/options
php bin/console app:list-overdue-tasks # all projects
php bin/console app:list-overdue-tasks 3 # only project ID 3
php bin/console app:list-overdue-tasks --count-only
php bin/console app:list-overdue-tasks 3 --count-onlyInteractive prompts for missing required input
if ($io->confirm('Really mark all overdue tasks as done?', false)) {
// ... update tasks ...
}
$answer = $io->ask('New status for all found tasks', 'in_progress');confirm() asks a yes/no confirmation (with a default value as the second argument), ask() asks for free text – both pause execution until the user answers in the terminal. USEFUL for interactive use, but problematic for AUTOMATED scripts.
Achtung: Interactive prompts BLOCK indefinitely in automated contexts (cron jobs, CI/CD, chapter 41), since NOBODY can answer – Symfony offers the --no-interaction flag (also -n) for this, which automatically answers ALL interactive prompts with their default value. Commands meant to also run automated MUST work with --no-interaction.
Showing help for a command
php bin/console app:list-overdue-tasks --helpTipp: --help shows AUTOMATICALLY generated documentation for ALL arguments and options, including the description texts from the attributes – another reason to always word THESE meaningfully instead of leaving them empty.