Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 output any HTML controller as JSON

Tags:

symfony

I have a website completed that was created in Symfony2 and I now want a lot of the features of the site to now be made available in a mobile app.
My idea is by appending a simple URL variable then it will output all the variables of the relevant page request in JSON.

So if I connect to

www.domain.com/profile/john-smith

It returns the HTML page as now.
But if I go to

www.domain.com/profile/john-smith?app

Then it returns a JSON object of name, age and other profile info.
My app code then receives the JSON and processes.

I can't see any security issues as it's just really the variables presented in JSON and no HTML.

By doing the above I can create all the app code and simply make calls to the same URL as a web page, which would return the variables in JSON and save the need for any more server-side work.

The question is: How would I do this without modifying every controller?

I can't imagine an event listener would do it? Maybe I could intercept the Response object and strip out all the HTML?

Any ideas as to the best-practice way to do this? It should be pretty easy to code, but I'm trying to get my head around the design of it.

like image 909
user2143356 Avatar asked Mar 15 '13 09:03

user2143356


1 Answers

There is a correct way to configure the routes for this task

  article_show:
  path:     /articles/{culture}/{year}/{title}.{_format}
  defaults: { _controller: AcmeDemoBundle:Article:show, _format: html }
  requirements:
      culture:  en|fr
      _format:  html|rss
      year:     \d+

However, this would still require you to edit every Controller with additional control structures to handle that output.

To solve that problem, you can do two things.

  1. Create json templates for each template you have, then replace html in template.html.twig with template.'.$format.'.twig. (Be careful to ensure users can't pass a parameter without validation in the url, this would be a major security risk).

  2. Create your own abstract controller class and override the render method to check the requested format and provide output based on that.

    class MyAbstractController extends Symfony\Bundle\FrameworkBundle\Controller\Controller
    {
        public function render($view, array $parameters = array(), Response $response = null)
        {
            if($this->getRequest()->getRequestFormat() == 'json')
            {
                return new Response(json_encode($parameters));
            }
            else
            {
               parent::render($view, $parameters, $response);
            }
        }
    }
    

NOTE The above code is a prototype, don't expect it to work out of the box.

I personally would deem the second method more correct, because there is no duplication of code, and less security concern.

like image 95
james_t Avatar answered Nov 11 '22 22:11

james_t