Contents
Introduction:
Hello fellow dev, in this blog I will be showing you how to make a Symfony 7 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 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 7.
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:
- Composer
- Symfony CLI
- MySQL
- PHP >= 8.2
Tutorial Video:
Step 1: Install Symfony 7
First, select a folder where you want Symfony to be installed then execute this command on Terminal or CMD to install:
Install via composer:
composer create-project symfony/skeleton:"7.0.*" symfony-7-rest-api
Install via Symfony CLI:
symfony new symfony-7-rest-api --version="7.0.*"
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 symfony/orm-pack
composer require --dev symfony/maker-bundle
Step 3: 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 update 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.
# https://symfony.com/doc/current/configuration/secrets.html
#
# 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=02d13e9ed054ebe54f699d5b595d3081
###< 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://usearname:password@127.0.0.1:3306/symfony_7_rest_api?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
# DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
After configuring the database, execute this command to create the database:
php bin/console doctrine:database:create
Step 4: 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 5: 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\ORM\EntityManagerInterface;
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(EntityManagerInterface $entityManager): JsonResponse
{
$products = $entityManager
->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(EntityManagerInterface $entityManager, Request $request): JsonResponse
{
$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(EntityManagerInterface $entityManager, int $id): JsonResponse
{
$project = $entityManager->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(EntityManagerInterface $entityManager, Request $request, int $id): JsonResponse
{
$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(EntityManagerInterface $entityManager, int $id): JsonResponse
{
$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 6: 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 use Postman to test our API, but you can use your preferred tool.
POST Request – This request will create a new resource.
GET Request – This request will retrieve all the resources.
GET Request (with id) – This request will retrieve a particular resource.
PUT Request or you can use the PATCH Request – This request will update a resource.
DELETE Request – This request will delete a resource.