How to make Symfony 6 REST API

How to make Symfony 6 REST API

Avatar photoPosted by

Introduction:

Hello fellow dev, in this blog I will be showing you how to make a Symfony 6 REST API. REST API is used for communication between the client and server. REST stands for representational state transfer and API stands for application programming interface. REST API or also known as RESTful API is a type of API that uses the REST architectural style, an API is REST if it has these characteristics:

  • Client-Server – The communication between Client and Server.
  • Stateless – After the server completes an HTTP request, no session information is retained on the server.
  • Cacheable – Response from the server can be cacheable or non-cacheable.
  • Uniform Interface – These are the constraints that simplify things. The constraints are Identification of the resources, resource manipulation through representations, self-descriptive messages, and hypermedia as the engine of the application state.
  • Layered System – These are intermediaries between client and server like proxy servers, cache servers, etc.
  • Code on Demand(Optional) – This is optional, the ability of the server to send executable codes to the client like java applets or JavaScript code, etc.

Now you have a bit of insight about REST API. we will now proceed with creating this on Symfony 6.

What is Symfony? Symfony is a PHP framework used to develop web applications, APIs, microservices, and web services. Symfony is one of the leading PHP frameworks for creating websites and web applications.

Prerequisite:

Tutorial Video:

Step 1: Install Symfony 6

First, select a folder that you want Symfony to be installed then execute this command on Terminal or CMD to install:

Install via composer:

composer create-project symfony/skeleton symfony-6-rest-api

Install via Symfony CLI:

symfony new symfony-6-rest-api

Step 2: Install Packages

After installing Symfony, we must install the necessary packages for our REST API. During the installation of the packages, it will ask you to execute the recipes, type y to confirm.

composer require jms/serializer-bundle
composer require friendsofsymfony/rest-bundle
composer require symfony/maker-bundle      
composer require symfony/orm-pack

Step 3: Configure FOSRest Bundle

Open the file config/packages/fos_rest.yaml and add these line:

config/packages/fos_rest.yaml

fos_rest:
    format_listener:
        rules:
            - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json, html ] }

Step 4: Set Database Configuration

After installing, open the .env file and set the database configuration. We will be using MySQL in this tutorial. Uncomment the DATABASE_URL variable for MySQL and updates its configs. Make sure you commented out the other DATABASE_URL variables.

.env

# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
#  * .env                contains default values for the environment variables needed by the app
#  * .env.local          uncommitted file with local overrides
#  * .env.$APP_ENV       committed environment-specific defaults
#  * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration

###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=e0710317861221371d185cc932acd15b
###< symfony/framework-bundle ###

###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8"
###< doctrine/doctrine-bundle ###

After configuring the database, execute this command to create the database:

php bin/console doctrine:database:create

Step 5: Create Entity and Migration

Entity– is a class that represents a database table.

Migration – like version control for the database that allows us to modify and share database schema with your team.

Execute this command to create an Entity:

php bin/console make:entity

After executing the command above, it will ask questions – follow the steps below:

Class name of the entity to create or update (e.g. BraveElephant):
 > Project
Project

 created: src/Entity/Project.php
 created: src/Repository/ProjectRepository.php
 
 Entity generated! Now let's add some fields!
 You can always add more fields later manually or by re-running this command.

New property name (press <return> to stop adding fields):
 > name

 Field type (enter ? to see all types) [string]:
 > string
string

 Field length [255]:
 > 255

 Can this field be null in the database (nullable) (yes/no) [no]:
 > no

 updated: src/Entity/Project.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > description

 Field type (enter ? to see all types) [string]:
 > text
text

 Can this field be null in the database (nullable) (yes/no) [no]:
 > no

 Add another property? Enter the property name (or press <return> to stop adding fields):
 >


           
  Success! 
           

 Next: When you're ready, create a migration with php bin/console make:migration

Now that we have finished creating an entity, we will then create a migration:

 php bin/console make:migration

This will create a migration file, inside the migration file containing SQL. we will then run the SQL using this command:

php bin/console doctrine:migrations:migrate

Step 6: Generate Controller

A Controller is the one responsible for receiving Requests and returning Responses.

Execute this command:

php bin/console make:controller ProjectController

After creating the Controller add these lines of codes:

src/Controller/ProjectController.php

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Request;
use App\Entity\Project;

#[Route('/api', name: 'api_')]
class ProjectController extends AbstractController
{
    #[Route('/projects', name: 'project_index', methods:['get'] )]
    public function index(ManagerRegistry $doctrine): JsonResponse
    {
        $products = $doctrine
            ->getRepository(Project::class)
            ->findAll();
  
        $data = [];
  
        foreach ($products as $product) {
           $data[] = [
               'id' => $product->getId(),
               'name' => $product->getName(),
               'description' => $product->getDescription(),
           ];
        }
  
        return $this->json($data);
    }


    #[Route('/projects', name: 'project_create', methods:['post'] )]
    public function create(ManagerRegistry $doctrine, Request $request): JsonResponse
    {
        $entityManager = $doctrine->getManager();
  
        $project = new Project();
        $project->setName($request->request->get('name'));
        $project->setDescription($request->request->get('description'));
  
        $entityManager->persist($project);
        $entityManager->flush();
  
        $data =  [
            'id' => $project->getId(),
            'name' => $project->getName(),
            'description' => $project->getDescription(),
        ];
          
        return $this->json($data);
    }


    #[Route('/projects/{id}', name: 'project_show', methods:['get'] )]
    public function show(ManagerRegistry $doctrine, int $id): JsonResponse
    {
        $project = $doctrine->getRepository(Project::class)->find($id);
  
        if (!$project) {
  
            return $this->json('No project found for id ' . $id, 404);
        }
  
        $data =  [
            'id' => $project->getId(),
            'name' => $project->getName(),
            'description' => $project->getDescription(),
        ];
          
        return $this->json($data);
    }

    #[Route('/projects/{id}', name: 'project_update', methods:['put', 'patch'] )]
    public function update(ManagerRegistry $doctrine, Request $request, int $id): JsonResponse
    {
        $entityManager = $doctrine->getManager();
        $project = $entityManager->getRepository(Project::class)->find($id);
  
        if (!$project) {
            return $this->json('No project found for id' . $id, 404);
        }
  
        $project->setName($request->request->get('name'));
        $project->setDescription($request->request->get('description'));
        $entityManager->flush();
  
        $data =  [
            'id' => $project->getId(),
            'name' => $project->getName(),
            'description' => $project->getDescription(),
        ];
          
        return $this->json($data);
    }

    #[Route('/projects/{id}', name: 'project_delete', methods:['delete'] )]
    public function delete(ManagerRegistry $doctrine, int $id): JsonResponse
    {
        $entityManager = $doctrine->getManager();
        $project = $entityManager->getRepository(Project::class)->find($id);
  
        if (!$project) {
            return $this->json('No project found for id' . $id, 404);
        }
  
        $entityManager->remove($project);
        $entityManager->flush();
  
        return $this->json('Deleted a project successfully with id ' . $id);
    }
}

Step 7: Run the Application

After finishing the steps above, you can now run your application by executing the command below:

symfony server:start

Test the API:

We will be using Postman for testing our API, but you can use your preferred tool.

POST Request – This request will create a new resource.

symfony 5 rest api create Binaryboxtuts

GET Request – This request will retrieve all the resources.

symfony 5 rest api index Binaryboxtuts

GET Request (with id) – This request will retrieve a particular resource.

symfony 5 rest api show Binaryboxtuts

PUT Request or you can use the PATCH Request – This request will update a resource.

symfony 5 rest api update Binaryboxtuts

DELETE Request – This request will delete a resource.

symfony 5 rest api delete Binaryboxtuts