Categories
PHP Programming Symfony Tutorials Web Dev

Symfony 5 RESTful API, quick intro for beginners

During this quick intro guide, you’ll easily learn the main principles of building a RESTful API, making use of the framework called Symfony, version 5.1.0, which you’ll already know, at least by name.

Symfony the PHP framework

This article follows another one with the same topic, this time we’ll be discussing the latest Symfony stable version, actually. It has been released this November of 2020, and it will be supported till July 2021.

As a prerequisite for this learning path I advice you to read this previous article which I wrote and mentioned above, just to install all the stuff needed for it to begin.

Now, either you’re on Windows, Linux or Machintosh, you should have a working 7.2.5 PHP installation along with MySQL, a Symfony installation, Composer, Git and cURL.

If not so, please refer to the many guides and tutorials you can find on the internet; they should be all right. Just put 10 minutes more on your schedule, and you’ll be up and running.

$ composer create-project symfony/website-skeleton symfony-5-rest-api 5.2.*
$ cd symfony-5-rest-api
$ composer require symfony/orm-pack
$ composer require annotations
$ composer require symfony/maker-bundle --dev

Modify the following line of the .env file, to establish a database connection, in a similar way to that:

DATABASE_URL="mysql://root:@127.0.0.1:3306/symfony_5_rest_api?serverVersion=mariadb-10.4.11

And than, create your database along with your entity, have a look at that lines of code:

$ php bin/console doctrine:database:create
$ php bin/console make:entity

You should create and Article entity with four string fileds, Title, Author, Body, Url. The next step is to create a migration for your project and apply that migration to your database, a new table will be created:

$ php bin/console make:migration
$ php bin/console doctrine:migrations:migrate

The next thing we should do is to create a controller for our Rest API, do the following step:

$ php bin/console make:controller ArticleController

And then modify our controller like this, with four CRUD operations along with four HTTP verbs. POST, GET, PUT, DELETE. We will create an article via out POST method:

/**
 * @Route("/article", name="add_article", methods={"POST"})
 */
public function add(Request $request): JsonResponse
{
	$title = $request->query->get('title');
	$author = $request->query->get('author');
	$body = $request->query->get('body');
	$url = $request->query->get('url');

	if (empty($title) || empty($author) || empty($body)) {
		throw new NotFoundHttpException('Expecting mandatory parameters!');
	}

	$this->articleRepository->saveArticle($title, $author, $body, $url);

	return new JsonResponse(['status' => 'Article created!'], Response::HTTP_CREATED);
}

Then we will read our articles one by one or all at the same time, this is done via out GET methods:

/**
 * @Route("/article/{id}", name="get_one_article", methods={"GET"})
 */
public function get($id): JsonResponse
{
	$article = $this->articleRepository->findOneBy(['id' => $id]);

	$data = [
		'title' => $article->getTitle(),
		'author' => $article->getAuthor(),
		'body' => $article->getBody(),
		'url' => $article->getUrl()
	];

	return new JsonResponse($data, Response::HTTP_OK);
}
/**
 * @Route("/articles", name="get_all_aricles", methods={"GET"})
 */
public function getAll(): JsonResponse
{
	$articles = $this->articleRepository->findAll();
	$data = [];

	foreach ($articles as $article) {
		$data[] = [
			'title' => $article->getTitle(),
			'author' => $article->getAuthor(),
			'body' => $article->getBody(),
			'url' => $article->getUrl()
		];
	}

	return new JsonResponse($data, Response::HTTP_OK);
}

We will update our articles via our PUT method:

/**
 * @Route("/article/{id}/params", name="update_article", methods={"PUT"})
 */
public function update($id, Request $request): JsonResponse
{
	$article = $this->articleRepository->findOneBy(['id' => $id]);

	$article->setTitle($request->query->get('title'));
	$article->setAuthor($request->query->get('author'));
	$article->setBody($request->query->get('body'));
	$article->setUrl($request->query->get('url'));

	$updatedArticle = $this->articleRepository->updateArticle($article);

	return new JsonResponse($updatedArticle->toArray(), Response::HTTP_OK);
}

And delete our articles, with the DELETE HTTP verb:

/**
 * @Route("/article/{id}", name="delete_article", methods={"DELETE"})
 */
public function delete($id): JsonResponse
{

	$article = $this->articleRepository->findOneBy(['id' => $id]);

	$this->articleRepository->removeArticle($article);

	return new JsonResponse(['status' => 'Article deleted'], Response::HTTP_NO_CONTENT);
}

Creating our entity will also create a repository file, look at that under our src folder on our application. You should see all the working code at this GitHub repository.

The last thing we have to remeber is to test our application, we begin by starting our Symfony server:

$ symfony server:start

All you have to do is to reach our endpoint, which is our controller with a cURL invocation, to test every CRUD operation:

$ 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/article
$ curl -v http://127.0.0.1:8000/article/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/article
$ curl -v http://127.0.0.1:8000/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/articles/1/params

$ curl -X DELETE http://127.0.0.1:8000/article/1
$ curl -v http://127.0.0.1:8000/articles

In this Tutorial you learned how to create a simple article Rest API example, with all the CRUD operations in place. Have a look at our GitHub, code speak for itself.

Did you like this post? Please, share it on your preferred social networks, thank you! Do you like the way I write code? Hire me! My email is on the homepage, let's make a chat to see if we can work together.