How to Call a Command from a Controller

How to Call a Command from a Controller

The Console component documentation covers how to create a console command. This article covers how to use a console command directly from your controller.

You may have the need to call some function that is only available in a console command. Usually, you should refactor the command and move some logic into a service that can be reused in the controller. However, when the command is part of a third-party library, you don’t want to modify or duplicate their code. Instead, you can run the command directly from the controller.

Caution

In comparison with a direct call from the console, calling a command from a controller has a slight performance impact because of the request stack overhead.

Imagine you want to send spooled Swift Mailer messages by using the swiftmailer:spool:send command. Run this command from inside your controller via:

  1. // src/Controller/SpoolController.php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Console\Application;
  4. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  5. use Symfony\Component\Console\Input\ArrayInput;
  6. use Symfony\Component\Console\Output\BufferedOutput;
  7. use Symfony\Component\HttpFoundation\Response;
  8. use Symfony\Component\HttpKernel\KernelInterface;
  9. class SpoolController extends AbstractController
  10. {
  11. public function sendSpool(int $messages = 10, KernelInterface $kernel): Response
  12. {
  13. $application = new Application($kernel);
  14. $application->setAutoExit(false);
  15. $input = new ArrayInput([
  16. 'command' => 'swiftmailer:spool:send',
  17. // (optional) define the value of command arguments
  18. 'fooArgument' => 'barValue',
  19. // (optional) pass options to the command
  20. '--message-limit' => $messages,
  21. ]);
  22. // You can use NullOutput() if you don't need the output
  23. $output = new BufferedOutput();
  24. $application->run($input, $output);
  25. // return the output, don't use if you used NullOutput()
  26. $content = $output->fetch();
  27. // return new Response(""), if you used NullOutput()
  28. return new Response($content);
  29. }
  30. }

Showing Colorized Command Output

By telling the BufferedOutput it is decorated via the second parameter, it will return the Ansi color-coded content. The SensioLabs AnsiToHtml converter can be used to convert this to colorful HTML.

First, require the package:

  1. $ composer require sensiolabs/ansi-to-html

Now, use it in your controller:

  1. // src/Controller/SpoolController.php
  2. namespace App\Controller;
  3. use SensioLabs\AnsiConverter\AnsiToHtmlConverter;
  4. use Symfony\Component\Console\Output\BufferedOutput;
  5. use Symfony\Component\Console\Output\OutputInterface;
  6. use Symfony\Component\HttpFoundation\Response;
  7. // ...
  8. class SpoolController extends AbstractController
  9. {
  10. public function sendSpool(int $messages = 10): Response
  11. {
  12. // ...
  13. $output = new BufferedOutput(
  14. OutputInterface::VERBOSITY_NORMAL,
  15. true // true for decorated
  16. );
  17. // ...
  18. // return the output
  19. $converter = new AnsiToHtmlConverter();
  20. $content = $output->fetch();
  21. return new Response($converter->convert($content));
  22. }
  23. }

The AnsiToHtmlConverter can also be registered as a Twig Extension, and supports optional themes.

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.