paul paul - 1 year ago 224
Ajax Question

Ajax polling with Symfony Process component

I am starting a long running task that returns incremental output about the tasks progress with the Symfony Process component.

One of the examples shows how to get real time output and another example shows how to run an asynchronous task.

What I am trying to achieve is sto pass the result of getIncrementalOutput back to the ajax polling function so I can update the front end in real time.

It seems in either case the process->start() is blocking because my ajax call takes a minute to return and by that time the task has finished.

I guess I'm trying to avoid writing the progress to a db or a file and get the output directly from the running PHP task.

Not sure it's possible.


Although I don't fully understand what you want to create, I have written something similar and looking at it might answer your question:

First I created a Command that does the long-running task:

class GenerateCardBarcodesCommand extends Command 
    protected function configure()
            ->setDescription('Generate the customer cards with barcodes')
            ->addArgument('id', InputArgument::REQUIRED, 'id of the Loy/Card entity')

    protected function execute(InputInterface $input, OutputInterface $output)
        $id = $input->getArgument('id');
        // generate stuff and put them in the database

In the controller the Process is started and there's an ajax action

class CardController extends Controller
    public function newAction(Request $request)
                // run command in background to start generating barcodes
                // NOTE: unset DYLD_LIBRARY_PATH is a fix for MacOSX develop using MAMP.
                // @see
                $process = new Process(sprintf('unset DYLD_LIBRARY_PATH ; php ../../apps/spin/console spin:loy:generate-card-barcodes %d', $entity->getId()));

                sleep(1); // wait for process to start

                // check for errors and output them through flashbag
                if (!$process->isRunning())
                    if (!$process->isSuccessful())
                        $this->get('session')->getFlashBag()->add('error', "Oops! The process fininished with an error:".$process->getErrorOutput());

                // otherwise assume the process is still running. It's progress will be displayed on the card index
                return $this->redirect($this->generateUrl('loy_card'));

    public function ajaxCreateBarcodesAction($id)
        $em = $this->getDoctrine()->getManager();
        $entity = $this->getEntity($id);
        $count = (int)$em->getRepository('ExtendasSpinBundle:Loy\CustomerCard')->getCount($entity);
        return new Response(floor($count / ($entity->getNoCards() / 100)));

// in the twig template the ajax is retrieved, which is simply a number from 0 to 100, which is used in the jquery ui progressbar. {{ 'Processing'|trans }}...

            <script type="text/javascript">
            $(function() {
                function pollLatestResponse() {
                    $.get("{{ path('loy_card_ajax_generate_barcodes', {'id': entity[0].id}) }}").done(function (perc) {
                        if (perc == 100)
                            $('#progress-{{entity[0].id}}').progressbar("value", parseInt(perc));

                var pollTimer;
                $(document).ready(function () {
                    $('#progress-{{entity[0].id}}').progressbar({"value": false});
                    pollTimer = setInterval(pollLatestResponse, 2000);