Creating the simplest possible API with Symfony 4 and Docker
On November 30th 2017, Symfony team released the fourth version of the framework, Symfony 4. This version has lots of new features and modifies relevant aspects of older versions [1]:
- application bundles has been removed
- configuration parameters becomes environment variables
- improvements to the application directory structure
- Symfony Flex: the new tool to automatate repetitive tasks
- a smaller codebase
To test the installation process, I create a simple API; to be more precise, I create the simplest possible API in my opinion: a back-end with only one route, /ping, which will respond with the following JSON:
{ “ping”: “pong”}
Ok, it’s not the most exciting thing I’ve ever done, but it’s simple and fast.
Oh, and another thing: I will use Docker to create the development environment. Normally I use Vagrant and Puppet for Symfony-based projects, but I would like to test how Docker works in this use case.
So, let’s begin.
Install Docker (Community Edition). I won’t write how to install Docker in your system. You can find how to do that here: https://www.docker.com/community-edition#/download. Just for information, I use Docker for Mac (version 18.03.0-ce-rc4-mac57).
I don’t want to write custom Dockerfiles (I’m lazy and I don’t want to waste a morning to test them). A 30-second Google search allows me to find this repository on GitHub: https://github.com/eko/docker-symfony.
This is a complete stack for running Symfony 4 (latest version: Flex) into Docker containers using docker-compose tool.
669 stars, 284 forks and last commit: 15 days ago. Cool.
Just for information, the hash of the commit of the repo I will use for the project is b553a7d6b64f024c72790346943cb5f3986274dc.
git clone https://github.com/eko/docker-symfony simple-apicd simple-apidocker-compose up -d
Hopefully, you won’t receive any error:
…Creating simpleapi_db_1 … doneCreating simpleapi_php_1 … doneCreating simpleapi_nginx_1 … doneCreating simpleapi_elk_1 … done
With the command
docker ps
you will have the ids of the container (in the “CONTAINER ID” column). In my case, the image simpleapi_php has the following container id: 6ccf4ca77b10. We will use it in a moment.
You can install the new Symfony framework with the command:
docker exec 6ccf4ca77b10 composer create-project symfony/website-skeleton my-project
with 6ccf4ca77b10 your simpleapi_php container id. With this command, we in fact run the command
composer create-project symfony/website-skeleton my-project
in the container where composer has been installed during the composer up process.
I hope you won’t receive any error.
Now you have a folder ./symfony with ./symfony/var and ./symfony/my-project as subfolders. You have to move ./symfony/my-project files in ./symfony parent folder (after removing the useless ./symfony/my-project/var folder). At the end, you will have all Symfony files and directories (assets, bin, config, public, src, templates, etc.) in the ./symfony folder.
If you want to use git to version your code, you have to remove /symfony from the .gitignore file. Now you can commit your Symfony application code.
You can modify/delete also the LICENSE file and the README file.
You have to change your /etc/hosts file to allow your system using the host symfony.localhost. Add the following line at the end of the file:
127.0.0.1 symfony.localhost
Open your browser and go to symfony.localhost.
Oh, we have an error. But it’s a 404 Symfony error!
No route found for “GET /”
Nothing to worry about! We haven’t any route at the moment, so it’s normal!
We can write a route just for testing. With your favorite editor, create a file in the .symfony/src/Controller folder. Somtehing like HelloController.php:
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Annotation\Route;
class HelloController{ /** * @Route(“/hello”) */ public function helloAction() { return new Response( ‘<html><body>Hello World</body></html>’ ); }}
It’s a pretty simple Controller, in which we define a route /hello which responds with a HTML string.
Now go to symfony.localhost/hello with your browser and you will see “Hello World”. Wow.
But we would like to have a JSON response, so we change this file, renaming it from HelloController.php to PingController.php, and modifying the code a little bit:
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Annotation\Route;
class PingController{ /** * @Route(“/ping”) */ public function pingAction() { $response = new Response(); $response->setContent(json_encode(array( ‘ping’ => ‘pong’, ))); $response->headers->set(‘Content-Type’, ‘application/json’);
return $response; }}
UPDATE: As pointed out by Patrick Landolt, you can write also:
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\Routing\Annotation\Route;
class PingController{ /** * @Route("/ping") */ public function pingAction() { $response = new JsonResponse(array('ping' => 'pong'));
return $response; }}
Go to symfony.localhost/ping and jubilate with your favorite beer.
If you have lost something, you can read the code in the repository https://github.com/nicolanrizzo/simple-api.
But I have to write a real application, not a toy project!
We have seen how to return a simple JSON response. For a real application, you can use api-platform: https://api-platform.com.
Notes: