In this tutorial I’m gonna show you some basic tricks which will allow you to write a simple RESTful API, or at least to begin to.
If you read this previuos tutorial you’ll be aquainted with Symfony‘s CRUD operations and it’s gonna be easy for me to tell you how to proceed.

The first thing you’re gonna have to do is to setup your environment, to do that I advice you to install Xammp in order to have PHP and MySQL working on your machine.
Another useful installation is Git for Windows if you’re on Windows like me, just to have cURL installed. Otherwise if you’re on Linux or Mac, just install it with your package manager.
The second thing to do is to install Symfony and all the necessary dependencies:
$ composer create-project symfony/skeleton symfony-rest-api 4.4.*
$ cd symfony-rest-api
$ composer require symfony/serializer
$ composer require doctrine/annotations
$ composer require friendsofsymfony/rest-bundle
$ composer require symfony/orm-pack
$ composer require symfony/property-access
$ composer require symfony/web-server-bundle --dev
$ composer require symfony/maker-bundle --dev
Next you’ll have to configure your database settings inside Symfony’s installation, so edit the .env file on the root folder like so:
DATABASE_URL=mysql://yourusername:yourpassword@127.0.0.1:3306/blog?serverVersion=5.7
And now we have to create our database and a table in it, with an Article entity which will be our table. Follow these steps:
$ php bin/console doctrine:database:create
$ php bin/console make:entity
If you don’t remember how to crete this entity look again at the tutorial linked above. Then follow these steps to create a migration:
$ php bin/console make:migration
$ php bin/console doctrine:migrations:migrate
Let’s configure our rest routes and annotations inside the Symfony installation:
#config/packages/fost_rest.yaml
fos_rest:
view:
view_response_listener: true
format_listener:
rules:
- { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json ] }
#config/routes/annotations.yaml
rest_controller:
resource: ../../src/Controller/
type: annotation
prefix: /api
Ok then, it’s time to get our hands dirty with our Symfony code. Let’s first create some private helpers methods for our application. This is for serializing our output:
private function returnNormalized($param)
{
$encoders = [new JsonEncoder()];
$normalizers = [new ObjectNormalizer()];
$serializer = new Serializer($normalizers, $encoders);
return $serializer->serialize($param, 'json');
}
Wanna discover the other little magic under the hood? And a little bit of abstraction, for the full code of the tutorial, go to this GitHub. Now it’s time to put in place our REST methods, let’s begin with POST to create a new Article:
/**
* @Rest\Post("/articles")
* @param Request $request
* @return View
*/
public function postArticle(Request $request): View
{
$article = new Article();
$this->setArticleFields($article, $request);
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
return View::create($this->returnNormalized($article), Response::HTTP_OK);
}
Then we have our GET methods, to retrive one Article in particular, or everyone:
/**
* @Rest\Get("/articles/{id}")
* @param Request $request
* @return View
*/
public function getArticle(Request $request): View
{
$article = $this->getArticleById($request);
return View::create($this->returnNormalized($article), Response::HTTP_OK);
}
/**
* @Rest\Get("/articles")
* @return View
*/
public function getArticles(): View
{
$articles = $this->getDoctrine()
->getRepository('App\Entity\Article')
->findAll();
return View::create($this->returnNormalized($articles), Response::HTTP_OK);
}
It follows the PUT method, to update our Articles:
/**
* @Rest\Put("/articles/{id}")
* @param Request $request
* @return View
*/
public function putArticle(Request $request): View
{
$article = $this->getArticleById($request);
if ($article) {
$this->setArticleFields($article, $request);
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
}
return View::create($this->returnNormalized($article), Response::HTTP_OK);
}
The last thing to remember is the DELETE method:
/**
* @Rest\Delete("/articles/{id}")
* @param Request $request
* @return View
*/
public function deleteArticle(Request $request)
{
$article = $this->getArticleById($request);
if ($article) {
$em = $this->getDoctrine()->getManager();
$em->remove($article);
$em->flush();
}
return View::create($this->returnNormalized($article), Response::HTTP_OK);
}
Alright, let’s run our application:
$ php bin/console server:run
And test it, in another terminal with cURL. Make it like this: create an article, see that it is created. Create another one, see that both are present now. Update it, see that it is updated. Delete the first, see that there’s only one remaining. That’s all.
$ curl -H "Content-Type: application/json" -d "{\"title\":\"Article Title\", \"author\":\"Mirko Benedetti\", \"body\":\"Article Body\", \"url\":\"Article Url\"}" http://127.0.0.1:8000/api/articles
$ curl -v http://127.0.0.1:8000/api/articles/1
$ curl -H "Content-Type: application/json" -d "{\"title\":\"Second Title\", \"author\":\"Mirko Benedetti\", \"body\":\"Second Body\", \"url\":\"Second Url\"}" http://127.0.0.1:8000/api/articles
$ curl -v http://127.0.0.1:8000/api/articles
$ curl -X PUT -H "Content-Type: application/json" -d "{\"title\":\"Updated Title\", \"author\":\"Francesco Angeli\", \"body\":\"Updated Body\", \"url\":\"Updated Url\"}" http://127.0.0.1:8000/api/articles/1
$ curl -v http://127.0.0.1:8000/api/articles/1
$ curl -X DELETE http://127.0.0.1:8000/api/articles/1
$ curl -v http://127.0.0.1:8000/api/articles
In this brief tutorial you learned how to build a basilar RESTful API with the help of Symfony.
Did you like this post? Please, share it on your preferred social networks or comment here below, thank you!
Hi there. My name is Mirko Benedetti, I’m a Software Developer and I founded this website. Excellence is what I consider to be our ultimate goal, and passion for technology constantly drives me to it. I began programming self-taught at a very young age. Since then I learned a lot, and every day I’m learning new things.
Great article! However, you missed a dependency which is required to handle and convert JSON requests:
composer require symfony-bundles/json-request-bundle