Symfony a RESTFul app: REST Levels 3 ( BazingaHateoasBundle )

In the previous post we set up a basic symfony project aiming to develop a RESTFul solution.

Great we are now on the last level of the REST model, the Hypermedia Controls. What are Hypermedia Controls, as Martin Fowler explains:

There’s no absolute standard as to how to represent hypermedia controls.

So this post its about how we can deliver this Hypermedia Controls on our RESTFul apps using the proposal from Martin Fowler and Leonard Richardson.

As always all the code on this series can be found on this github repository under the symfony2_restful_example branch.


In the article Martin Fowler say:

HATEOAS (Hypertext As The Engine Of Application State). It addresses the question of how to get from a list open slots to knowing what to do to book an appointment.

With this links the client can follow the directions on what to do with the given resource even if they don’t know the documentation of your API.

Since the Hypermedia Control links should be relative they allow the flexibility to change the domain holding the api without braking the map.

There is an implementation of this specification for PHP you can find it at and of course the symfony bundle:


This bundle is developed by William Durand the same developer of the base hateoas php library. It allow us to integrate this Hypermedia Control in our REST APIs. The bundle is well documented you can check it on

Lets install it using composer

composer require willdurand/hateoas-bundle

And enable it on the AppKernel

new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),

As described on the doc this bundle require the JMSSerializerBundle but since we already have it installed from the previous posts there is nothing extra to do.

At this point we have the bundle configured so lets map some Hypermedia Controls on our entities, lets use the Customer


namespace AppBundle\Entity;

use Customer\Customer as CustomerBase;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation as Serializer;

 * Customer ORM Entity
 * @Serializer\XmlRoot("customer")
 * @Hateoas\Relation("self", href = @Hateoas\Route("get_customers", parameters = { "customer" = "expr(object.getId())" }))
 * @Hateoas\Relation("customers", href = @Hateoas\Route("cget_customers"))))
class Customer extends CustomerBase

We are defining two relations, one with it self and one with the collection so the client can easily navigate through our api following the directions we gave.

One call to the end point for an specific customer, lets take this example /customers/55eeec8f80c0f should respond with something like this:

id: "55eeec8f80c0f"
username: "fabien"
username_canonical: "fabien"
email: ""
email_canonical: ""
enabled: true
salt: "aru3jkvy1r4gcoock4gwocko0w8w4sk"
password: "$2y$13$aru3jkvy1r4gcoock4gwoO2/lUF5PVlUHOqJIUCX9geX7jZxxjTfC"
locked: false
expired: false
credentials_expired: false
links: {
  self: {
    href: "/customers/55eeec8f80c0f"
  customers: {
    href: "/customers"

The library expose several annotations and helpers that we can use to build this expressive Hypermedia Control map, but for the sake of the extensiveness of this post i will leave it to you.


Following the good practices and applying for all the levels of the REST model, we manage to build a simple RESTFul app, sure its really simple at the point of useless, but the aim of this post series is to demonstrate how a RESTFul app should look alike; again your business rules will guide you through the process on what to build but sure this practices will lead you to a great RESTFul app.

One more post remains to talk about security, this is topic where there is not a single line write on stone, there are so many ways to implement it, that post will be just a single reference on how to put it all together and an advice to use OAuth 2.0.


  1. Motivation
  2. REST Levels 0, 1, 2 ( FOSRestBundle, JMSSerializerBundle )
  3. REST Levels 0, 1, 2 ( FOSUserBundle )
  4. REST Levels 0, 1, 2 ( NelmioApiDocBundle )
  5. REST Levels 3 ( BazingaHateoasBundle )
  6. Security ( FOSOAuthServerBundle )
  7. Security ( Securing the token path )
  8. Security ( Securing the token path – FIXED )


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s