Composing Commands & Machine Output
Calling a Command from Another
<?php
protected function execute(InputInterface $input, OutputInterface $output): int
{
$syncCommand = $this->getApplication()->find('app:sync');
$syncInput = new ArrayInput(['--force' => true]);
$returnCode = $syncCommand->run($syncInput, $output); // runs in-process, no subprocess
if ($returnCode !== Command::SUCCESS) {
return $returnCode;
}
// ...continue with this command's own work
return Command::SUCCESS;
}Interactive Prompts
<?php
use Symfony\Component\Console\Question\ChoiceQuestion;
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$env = $io->choice('Which environment?', ['dev', 'staging', 'production'], 'dev');
if ($env === 'production' && !$io->confirm('This targets PRODUCTION. Continue?', false)) {
return Command::FAILURE;
}
// ...
return Command::SUCCESS;
}Machine-Readable Output
<?php
protected function configure(): void
{
$this->addOption('format', null, InputOption::VALUE_REQUIRED, 'text or json', 'text');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$results = $this->fetchResults();
if ($input->getOption('format') === 'json') {
$output->writeln(json_encode($results)); // pipeable into jq, other tools
} else {
(new SymfonyStyle($input, $output))->table(['ID', 'Status'], $results);
}
return Command::SUCCESS;
}
// php bin/console app:report --format=json | jq '.[0]'Graceful Shutdown
<?php
use Symfony\Component\Console\Command\SignalableCommandInterface;
class LongRunningCommand extends Command implements SignalableCommandInterface
{
private bool $shouldStop = false;
public function getSubscribedSignals(): array
{
return [SIGTERM, SIGINT];
}
public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
{
$this->shouldStop = true; // finish current unit of work, then exit cleanly
return false;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
while (!$this->shouldStop && $this->hasMoreWork()) {
$this->processNext();
}
return Command::SUCCESS;
}
}Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free