visit our site
APIs in Symfony2

Getting Started with Building APIs in Symfony2

In PHP and Symfony

by Costi on November 3, 2015

Hello all you Interwebs friends! While we’re passing through the shallow mists of time, REST is becoming more and more of a universal standard when building web applications. That said, here’s a very brief tutorial on how to get started with building APIs in Symfony2.

Spoiler alert: the bits of code written below use FosUserBundle + Doctrine.

1. Generate a New Bundle

It’s nice to keep your code neat and tidy, so ideally, you should create a separate bundle that will only store your API code, we can generically name ApiBundle.

 

2.  Versioning

This isn’t by any means mandatory, but if you believe that your API endpoints will suffer major changes along the way, that cannot be predicted from the get go, it would be nice to version your code. This means that you would, initially, have a prefix in your endpoints, like: /v1/endpoint.json, and you’d increase that value each time a new version comes along. I’ll describe how to actually create the first version (v1) of your API a little further down the line.

3. Install a Few Useful Bundles

  • FosRestBundle – this bundle will make our REST implementation a lot easier.

and then include FOSRestBundle in your AppKernel.php file:

  • JmsSerializerBundle – this will take care of the representation of our resources, converting objects into JSON.

and then include JMSSerializerBundle in your AppKernel.php:

 

4. Configurations

Configure the Response object to return JSON, as well as set a default format for our API calls. This can be achieved by adding the following code in app/config/config.yml:

 

5. Routing

I prefer using annotations as far as routes go, so all we need to do in this scenario would be to modify our API Controllers registration in /app/config/routing.yml. This registration should have already been created when you ran the generate bundle command. Now we’ll only need to add our version to that registration. As far as the actual routes of each endpoint go, we’ll be manually defining them later on, in each action’s annotation.

At this point we’re all set to start writing our first bit of code. First off, in our Controller namespace, we would want to create a new directory, called V1. This will hold all of our v1 API Controllers. Whenever we want to create a new version, we’ll start from scratch by creating a V2 namespace and so on.

After that’s done let’s create an action that will GET a user (assuming we’ve previously created a User entity and populated it with users). This would look something like:

If we want to GET a list of all users, that’s pretty straightforward as well:

With that done, when running a GET request on https://yourapp.com/api/v1/users/1.json, you should get a json response with that specific user object.

What about a POST request? Glad you asked! There are actually quite a few options to do that. One would be to get the request data yourself, validate it and create the new resource yourself. Another (simpler) option would be to use Symfony Forms which would handle all this for us.

The scenario here would be for us to add a new user resource into our database.

If you’re also using FosUserBundle to manage your users, you can just use a similar RegistrationFormType:

Next, we’ll want to actually create our addUserAction():

To make a request, you’ll need to send the data as raw JSON, to our https://yourapp.com/api/v1/users/new.json POST endpoint:

 

And that’s all there is to it.

We haven’t covered the cases where you’d want Delete or Update a user yet. Updating resources through the REST standards can be done using either PUT or PATCH. The difference between them is that PUT will completely replace your resource, while PATCH will only, well, patch it… meaning that it will partially update your resource with the input it got from the API request.

Let’s get to it then. We’ll use the same form as before, and we’ll try to only change (we’ll use the PATCH verb for that) the email address, username and password of our previously created user:

The request body is the same as the one shown for the POST method, above. There are a few small differences in our edit action though. First off – we’re telling our form to use the PATCH method. Second – we are handling the case where the user ID provided isn’t found.

The Delete method is the easiest one yet. All we need to do is to find the user and remove it from our database. If no user is found, we’ll throw a “user not found” error:

Related: Routing in Symfony2

Conclusions

Aaand we’re done. We now have a fully working CRUD for our User Entity. Thanks for reading and please do share your opinions/suggestions in the comment section below.

13 Replies to “Getting Started with Building APIs in Symfony2”

  1. Hi their, how can i use this api in android application ! show me an example to get all user and show them in android application can u !

  2. Great tutoria, i only have one comment: is more cleaner using the http verbs or method of the request with same routing path, for example, “/user/{id} with GET method return the user, the same route with DELETE delete the user and with PUT/PATCH method update the user. The route “/users” with GET method return all users, but with POST method create a new user.

  3. if ($user){
    $em->remove($user);
    $em->flush();
    } else {
    throw $this->createNotFoundException(‘User not found!’);
    }

    throwing not found exception if user is not found during deletion is not correct. this method should always return 204 for success responses.
    It works like this. If user was found and successfully purged then 204 code says: this user is not present in database anymore. If you try to delete deleted user you also set 204 code and in this case it also says that user with requested ID is not present in DB. So DELETE method deletes user only if it exists, in other cases it should not throw an exception, just say: OK user doesn’t exist in the database, here is your 204 code

Leave a Reply

Your email address will not be published. Required fields are marked *

+1
Share1
Tweet
Share
Stumble
Pin