29/04/2017 - SYMFONY
In this example, we are going to call console command from controller and display the response as output arrives rather than displaying whole output in one go. For that we will be using StreamedResponse class of symfony and create our own streaming output class.
namespace Football\FrontendBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class SayHelloCommand extends Command
{
protected function configure()
{
$this
->setName('say:hello')
->addOption('name', null, InputOption::VALUE_REQUIRED)
->addOption('iteration', null, InputOption::VALUE_REQUIRED);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
for ($i = 1; $i <= $input->getOption('iteration'); $i++) {
$output->writeln(sprintf('%d: Hello %s', $i, $input->getOption('name')));
sleep(1);
}
}
}
services:
football_frontend.command.say_hello:
class: Football\FrontendBundle\Command\SayHelloCommand
tags:
- { name: console.command }
Test output in terminal.
football$ bin/console say:hello --name=Inanzzz --iteration=5
1: Hello Inanzzz
2: Hello Inanzzz
3: Hello Inanzzz
4: Hello Inanzzz
5: Hello Inanzzz
namespace Football\FrontendBundle\Controller;
use Football\FrontendBundle\Command\SayHelloCommand;
use Football\FrontendBundle\Service\StreamedOutput;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* @Route("", service="football_frontend.controller.default")
*/
class DefaultController
{
private $sayHelloCommand;
public function __construct(
SayHelloCommand $sayHelloCommand
) {
$this->sayHelloCommand = $sayHelloCommand;
}
/**
* @Method({"GET"})
* @Route("")
*
* @return Response
*/
public function streamAction()
{
$response = new StreamedResponse(function() {
$input = new ArrayInput([
'--name' => 'Inanzzz',
'--iteration' => 5,
]);
$input->setInteractive(false);
$output = new StreamedOutput(fopen('php://stdout', 'w'));
$this->sayHelloCommand->run($input, $output);
});
return $response;
}
}
services:
football_frontend.controller.default:
class: Football\FrontendBundle\Controller\DefaultController
arguments:
- '@football_frontend.command.say_hello'
namespace Football\FrontendBundle\Service;
use RuntimeException;
use Symfony\Component\Console\Output\StreamOutput;
class StreamedOutput extends StreamOutput
{
protected function doWrite($message, $newline)
{
if (
false === @fwrite($this->getStream(), $message) ||
(
$newline &&
(false === @fwrite($this->getStream(), PHP_EOL))
)
) {
throw new RuntimeException('Unable to write output.');
}
echo $message;
ob_flush();
flush();
}
}
If you go to your home page, you'll response displayed on the page every second one by one.
1: Hello Inanzzz2: Hello Inanzzz3: Hello Inanzzz4: Hello Inanzzz5: Hello Inanzzz