My Symfony command template

Published on 2019-11-24 • Modified on 2019-11-24

You can generate a command with the maker bundle (php bin/console make:command). I use a slightly different template where the help text is dynamically generated with constants. These are also used as parameters to set the various options, so you don't have duplicated code. Remove the constructor parameter as it is specific to this blog (It's a parameter bound in services.yaml). To run the command, I will use a CommandTester this time instead of using the Process component.


<?php declare(strict_types=1);

// src/Command/ShowVersionCommand.php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Display the current application version. This is also the template I copy/paste
 * when havinf to write a new command.
 */
final class ShowVersionCommand extends Command
{
    public const NAMESPACE = 'strangebuzz';
    public const CMD = 'version';
    public const DESC = 'Shows the current application version number.';

    private string $appVersion;

    public function __construct(string $appVersion)
    {
        parent::__construct();
        $this->appVersion = $appVersion;
    }

    protected function configure(): void
    {
        [$namespace, $cmd, $desc, $class] = [self::NAMESPACE, self::CMD, self::DESC, self::class];
        $this
            ->setName($namespace.':'.$cmd)
            ->setDescription(self::DESC)
            ->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
            ->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
            ->setHelp(
                <<<EOT
{$desc}

COMMAND:
<comment>{$class}</comment>

DEV:
<info>%command.full_name% -vv</info>

PROD:
<info>%command.full_name% --env=prod --no-debug</info>
EOT
            );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $io->note(self::NAMESPACE.' '.$this->appVersion);
        $io->success(' -> DONE!');

        return self::SUCCESS;
    }
}
Bonus, the snippet to run this code: 🎉
<?php declare(strict_types=1);

namespace App\Controller\Snippet;

use App\Command\ShowVersionCommand;
use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Process\Process;

/**
 * I am using a PHP trait to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 *
 * @property KernelInterface    $kernel
 * @property ShowVersionCommand $showVersionCommand
 */
trait Snippet58Trait
{
    public function snippet58(): void
    {
        $process = new Process([
            'php',
            $this->kernel->getProjectDir().'/bin/console',
            'strangebuzz:version',
            '--ansi',
        ]);
        $process->run();

        echo (new AnsiToHtmlConverter())->convert($process->getOutput()); // That's it! 😁
    }
}

 Run this snippet  More on Stackoverflow   Read the doc  Random snippet