2

So I have a basic requirement: I need to call a Symfony2's custom console command from a controller (the script is also called by a CRON job but I want it to be callable from a web-browser).

I followed this tutorial to make it work and here it is:

<?php

namespace AppBundle\Controller\Admin;

use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class TacheController extends Controller
{
    /**
     * @Route("/admin/taches/facebook", name="admin_tache_facebook")
     *
     * @return Response
     */
    public function facebookAction(Request $request)
    {
        ini_set('max_execution_time', -1);
        $kernel = $this->get('kernel');
        $application = new Application($kernel);
        $application->setAutoExit(false);

        $input = new ArrayInput(array(
            'command' => 'nrv:fetch:facebook',
        ));
        // You can use NullOutput() if you don't need the output
        $output = new BufferedOutput();
        $application->run($input, $output);

        // return the output, don't use if you used NullOutput()
        $content = $output->fetch();

        // return new Response(""), if you used NullOutput()
        return new Response($content);
    }
}

However, the console command is quite long to run (~2mn) and therefore, the page hangs for that time until it displays all the output from the command.

My goal is to have the output as it is displayed in the console like when using the web console with ConsoleBundle. I thought of the use of ob_start() and ob_end_flush() but I don't know how to use them in this context.

Is what I'm trying to achieve even possible? How can I make it so?


Solution

As per the answer provided by @MichałSznurawa, I had to extend \Symfony\Component\Console\Output\BufferedOutput and implements doWrite() method. Here it is:

<?php

namespace AppBundle\Console;

use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\HttpFoundation\StreamedResponse;

class StreamedOutput extends BufferedOutput
{
    public function doWrite($message, $newline)
    {
        $response = new StreamedResponse();
        $response->setCallback(function() use($message) {
            echo $message;
            flush();
        });

        $response->send();
    }
}

And amend the controller as per the following:

$output = new StreamedOutput();

The result is the page streaming the output of the command as soon as it get executed (instead of waiting for it to finish).

3
  • Do I understand you: are you trying to call from command line using webconsole a controller which should run a command? Commented May 24, 2016 at 20:32
  • Sorry if I'm not clear enough: I want to access to a controller via a specific URL which will run a Symfony2 console command. However, I want the output of the console immediately displayed to the user instead of waiting for the command to finish before display everything all at once. Commented May 24, 2016 at 20:34
  • @D4V1D I tried your example and it doesn't print messages one after another. All the messages get dumped in one go. Do you mind sharing a simple working example? Something that streams Hello, World at least. Maybe in here. Commented Apr 29, 2017 at 15:03

1 Answer 1

1

You will have to implement own output class and inject it instead of BufferedOutput. You can extend abstract class \Symfony\Component\Console\Output\Output or implement interface vendor/symfony/symfony/src/Symfony/Component/Console/Output/OutputInterface.php:20.

Your implementation should be streaming responses like described here: http://symfony.com/doc/current/components/http_foundation/introduction.html#streaming-a-response instead of waiting for end of execution of command and sending back all output together. That will work of course only if your command prints something during an execution.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.