Getting started REST API with Symfony 4

The concept of the Internet of things is a trending topic and it has found implementation in numerous aspects. Computers, laptops, mobile phones, and other non-internet-enabled physical devices like cars, or smart grids can interact with each other. To do it they need a standardized interface called API (application programming interface). The advantage of using a unified interface is once you implement such a web service on your server, it can interact with a variety of client devices. In addition, it gives the ability to build a web application with separate back-end and front-end parts. You may use modern JS frameworks to make user interfaces more dynamic and achieve good UX. Many organizations integrate their mobile applications with back-end CRM, ERP, EAM, and other tools to improve their productivity.

We considered how to create API using the headless Drupal 8 approach in our previous articles, find them in the Useful links block. However, the functionality of a CMS may not have enough flexibility for the projects with complex business logic. In such cases, using a PHP framework may become a more preferable option. 

Symfony is one of the most popular Open Source PHP frameworks consisting of separate components. They are used in many large projects, such as Drupal 8 or Laravel. Symfony has an active community and stable support. Also, it has the expandable architecture of reusable components called “bundle”, it extends the functionality of the framework. The latest Symfony version has a lot of improvements, such an automatic configuration of bundles with Symfony Flex and simplified folder structure increase the speed of development.

In this Symfony 4 tutorial, we will create a basic server back-end structure for your application using the REST API architecture style. We will use a 'FOSRestBundle' bundle as a basis, implement 'get' and 'post' methods to create and show the list of resources respectively. Besides that, we will add the OAuth2 authentication with FOSOAuthServerBundle.

Create a Rest API

Firstly, make sure you have installed PHP 7.1 or a higher version and the Composer package manager to create a new Symfony application. After that, create a new project by executing the following command in the terminal:

We use a basic Symfony skeleton project that is recommended for more barebones applications like microservices and APIs. Symfony 4.x has a new and more simplified directory structure. Here is what it looks like:

The default directory structure of a Symfony 4 project

The config directory contains all bundles configuration files and a list of enabled bundles in the bundles.php file. Symfony 4 will automatically register all bundles after the installation using Symfony flex recipes.
The public folder provides access to the application via the index.php entry point whereas the src folder contains all controllers, custom services, and objects. The var directory contains system logs and cache files. The vendor folder contains all external packages. 

Now let’s install some necessary bundles with composer 
 

Besides the friendsofsymfony/rest-bundle, we also installed the sensio/framework-extra-bundle. It will help us to make code easier to read by using annotations for defining our routes. 

We will use jms/serializer-bundle to serialize and deserialize resources of the application. We do have some validation requirements in our testing entity. Because of this, it’s also necessary to add a validator bundle. The form bundle will help us to handle incoming user data and convert it into a resource entity. We need to install symfony/orm-pack for the integration with Doctrine ORM to connect with a database. Database configuration may be set in the .env file.
 

As a result, our bundles.php file should look like:

After we have finished with the installation, let's create a test resource entity. Create a new file called Movie.php inside the src/Entity folder

Run the bin/console doctrine:schema: create command in the application directory to create a database structure according to our movie class with Doctrine ORM. We need to create a simple form for the Movie entity inside the src/Form folder to handle and validate a user’s request to post a new movie:

At the next step, set the following configuration for the fos_rest bundle
and add this code to the bottom of services the .yaml config file

to resolve the issue when FOS Rest Bundle is incompatible with the Sensio Framework Extra Bundle (https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1768).

Now it’s time to create a controller where we will add two methods to create a new movie and get the list of all the movies. As you understand, it should be placed inside the src/Controller folder.

Here we defined two routes, GET ‘/api/movies’ will return to us the list of all the movies. The POST ‘/api/movie’ request will run data validation with a Symfony form and create a new movie resource if data is valid. Ok, we have finished with the basic structure, let’s check how it works. First thing, try to create a couple of new resources by sending data in a JSON format.
The example of the post API request
Then we can receive them back using the GET request.
The example of the GET API request

OAuth2 authorization

There are several authorization methods for rest APIs and OAuth2 is one of the most popular. It allows using auth details from an external provider like Google or Facebook to identify yourself. In our application, we will use FOSUserBundle as a user provider, install this bundle with composer, then install FOSOAuthServerBundle as it is shown here:

Now you need to create necessary classes for a client and an access token according to the FOSOAuthServerBundle documentation and specify them in the fos_auth_server.yaml config file

Import routes from fos_auth_server bundle into config/routes.yaml

Create a user class for FOSUserBundle

and add a config file for UserBundle
This code should be in the security.yaml file
There we have made /api routers available for authenticated users only by adding it in the access_control block.
The example of the unauthorized request
After we finish the bundles’ configuration, we need to create an OAuth client and User to generate access tokens. To do this, let’s add a test controller
In your request to /createClient, you need to specify the redirect URIs you want to use, and the grant types you want to allow this client to use.
The request to create a new API client
A test user may be created with the console command bin/console fos:user:create test_user.
The command to create a new test user
Now we can get the access token, by making a POST request to the OAuth2 bundle route /oauth/v2/token.
Request to get a new access token

If everything is going right, we should receive the access token that we should send to the API request in headers, as follows

Authorization: Bearer NzQyNDg4YTJmMDFlYTgzMGE0ZWFjYWE0ZTgwMzhlN2YzODAxZjUyZGRlZjQyNzMyY2E5MzY1MDk3OTZhYzJhOQ

That’s all for now, our API Platform implementation completed. We have added two endpoints to create and show the list of resources and added OAuth2 authorization. If you have missed something, you can check the code in the repository.

Have fun building your own application!

 

Useful links

RESTful Web Services in Drupal 8 quick start guide

How to create a headless Drupal site

You might also like