Setting up FOSRestBundle with Symfony

This post is about me getting the REST bundle set up with Symfony, with a view to creating my SPA for noodledig. The idea is to use Symfony for the back-end API and angularjs for the front-end. There are a lot of considerations here, but the first step is to get the back-end api set up.

There are a load of suggestions on how to set up an angularjs app with a symfony back-end. The one that seems to make the most sense to me is to use FOSRestBundle. However, I didn’t find the instructions on setting it up all that helpful. So, here’s what I did…
To set up the FOSRestBundle, its got to be added to the composer.json and appkernel.php files…

//composer.json
"require": {
//...
"friendsofsymfony/rest-bundle": "1.3.*",
//...
//AppKernel.php
public function registerBundles()
{
  $bundles = array(
    //...
    new FOS\RestBundle\FOSRestBundle(),
    //...

FOSRestBundle has some other dependencies but I’m not going into that here. That’s all pretty straight-forward.
Once the appropriate code was added to the composer and AppKernel files, I ran the command ‘composer update’
To set up global settings for the REST bundle, I added the following to config.yml

#app/config/config.yml
#...
fos_rest:
    routing_loader:
        default_format: json

This says that the default format for data returned will be json. This doesn’t mean that other formats can’t be specified, but if no format is, the default is json.

The media api bundle

For my project, I need an API that can interact with other API’s like amazon, youtube, google etc and return data that will then be used by the angularjs app. So, I ran the command to generate my bundle using annotations for doctrine object relational mappings.

This bundle then needed to be modified to make it a ‘REST’ bundle.

Routing

The bundle must be defined as being of type ‘rest.’ A prefix can also be specified for all generated url’s.

#app/config/routing.yml
#...
sk_media_api_bundle:
    type: rest
    resource: "@SkMediaApiBundle/Resources/config/routing.yml"
    prefix:   /api

This routes urls with a prefix of ‘api’ to the above mentioned routing file.
So, inside that routing file, the following was defined…

sk_media_api:
    type: rest
    resource: Sk\MediaApiBundle\Controller\DefaultController
    name_prefix: sk_media_api_

This routes all requests to the DefaultController. Inside the controller, providing the action names follow the conventions laid out by the FOSRestBundle, everything works. The name prefix value can be used to avoid any route conflicts between different bundles.

A basic REST route

This is where I had the most problem. The controller needs to do the following –

  1. use the appropriate libraries – FOS\RestBundle\View\View
  2. call the actions by the correct name – so, the default action to get all the media types is called getMediatypesAction. The url that is generated from this is ‘/web/app_dev.php/api/mediatypes’. One key point here is that the actual action name must be only capitalised. If the action name is ‘getMediaTypesAction’ (capital T), the url generated is ‘/web/app_dev.php/api/media/types.’ It took me a while to figure this out. What helped to figure it out was the command ‘php app/console router:debug.’ This lists all urls in the project.
  3. Handle and return the view using FOSRestBundle’s handler –
    private function getViewHandler()
    {
      return $this->container->get('fos_rest.view_handler');
    }
    
    public function getMediatypesAction(){
      $em = $this->getDoctrine()->getManager();
      $mediaTypes = $em->getRepository('SkMediaApiBundle:MediaType')->getMediaTypes();
      $view = View::create()
        ->setData(array('mediaTypes' => $mediaTypes));
      return $this->getViewHandler()->handle($view);
    }
    

Conclusion

That’s about it. This is the first step in a long process but I’m getting somewhere! The next step is to work out a way to make the API calls secure so that only the angularjs app is authorised to call the API. Otherwise other apps could potentially use my API to call other API’s like Amazons, which would be bad.

Leave a Reply