Create a new Symfony 6 project and install the necessary dependencies
Our API will be based on the MVC (Models, Views and Controllers) structure or rather MC. Indeed, in the case of an API, we will not need to create and return HTML views. The returned results will all be in JSON format.
Let's start by creating the structure of our project. Since we are going to use the MVC structure, we will have to differentiate between Models and Controllers. First of all, let's create a first folder that we will name
models as well as another one that we will call
Let's stop this bad joke right now. Of course we are not going to create the structure of our project by hand. It would take way too much time, plus it will be simply useless because there are other tools that can do this same task automatically. To do this, we will use Composer.
Creating the Docker container
As we mentioned in the prerequisites, you can use Docker to encapsulate the application in a container. This allows you not to pollute your system with language versions that would be specific for this course. You will also have more freedom in the development.
If you want to use Docker, here is a configuration you can use.
As a reminder, if you already have PHP, MySQL (or another database system) and Composer, you can skip this step. In the same way, if you use a turnkey software like Laragon or Xampp, you can skip this step.
At the root of your project (in the
api folder we created earlier) start by creating a
Dockerfile with the following content.
# Dockerfile FROM php:8.1.17-apache WORKDIR /var/www ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/ RUN chmod +x /usr/local/bin/install-php-extensions RUN install-php-extensions pdo_mysql intl opcache zip COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer COPY ./.apache/vhosts.conf /etc/apache2/sites-available/000-default.conf CMD apachectl -D FOREGROUND
This file is used to define a custom Docker image. Let's review what this configuration file will do.
FROM php:8.1.17-apacheis used to define the image that we will use as a base. Here, it will be the image of PHP version 8.1.17 with the Apache module.
WORKDIR /var/wwwallows you to define the working directory. In other words, all the following commands will be executed from this directory. Here we choose
/var/wwwas this is the default directory for Apache.
- The following 3 lines allow you to install
docker-php-extension-installer, a utility tool that makes it easy to install and configure extensions for PHP within a Docker image. For our api, we will only need the following extensions:
- The following line allows to install Composer from the last Docker image
- Then we copy the contents of the file
.apache/vhosts.confof the host machine in the
/etc/apache2/sites-available/000-default.confof our Docker image.
CMD apachectl -D FOREGROUNDallows you to launch Apache.
Concerning the file
.apache/vhosts.conf, it allows you to specify the entry path for our application. Since we are going to use Symfony, the entry path will be the
# .apache/vhosts.conf <VirtualHost *:80> ServerName localhost DocumentRoot /var/www/public DirectoryIndex /index.php <Directory /var/www/public> AllowOverride None Order Allow,Deny Allow from All FallbackResource /index.php </Directory> ErrorLog /var/log/apache2/app.log CustomLog /var/log/apache2/app.log combined </VirtualHost>
In addition to our custom Docker image, we will need several other services. For example, we will need a database as well as a tool to visualize the data in our database.
Here is a configuration for the
docker-compose.yaml file in which we find the different services needed.
# docker-compose.yaml version: "3.8" services: database: command: --max-allowed-packet=64MB container_name: api-database image: mariadb environment: MYSQL_ROOT_PASSWORD: password volumes: - data:/var/lib/mariadb networks: - dev adminer: container_name: api-adminer image: adminer ports: - 8081:8080 networks: - dev depends_on: - database web: container_name: api-web build: context: . dockerfile: Dockerfile ports: - 8080:80 volumes: - ./:/var/www networks: - dev depends_on: - database volumes: data: networks: dev:
Creation of the Symfony project
Indeed, we are not going to create the structure by hand, we will rather use the Composer commands to facilitate our work.
Creating a Symfony project can be done in two different ways depending on the type of project you want:
The full version of a Symfony project will install all the packages needed to run any kind of project. This version will allow to create websites, command line interfaces or APIs. Unfortunately, in the case of an API, many packages will be useless and will increase the size of our project without really adding any utility.
The minimal version, on the other hand, will leave the field free on the installation of the desired packages. We will only be able to install what is necessary and not end up with useless packages. At the same time we will optimize the size of our project.
In our case, to create an API, we prefer to use the minimal version so that we don't end up with useless packages.
To create a Symfony project, start by opening a terminal and navigate to the location where you want to place the project.
Then run the following command:
composer create-project symfony/skeleton:6.2.* ./
This command will create the architecture of the project in minimal version (
skeleton) using the version
6.2 of Symfony. Here we enter the current directory (
./) as the destination.
Several new folders should have appeared at the place where you wanted to position the project.
Understanding the architecture of a Symfony project
A Symfony project is divided into different folders and subfolders. Indeed, as in any project, it's important to have a well ordered logic in order not to get lost or simply to collaborate on a project.
A Symfony application is broken down into 5 major folders:
bin: Gathers utility executables to launch Symfony commands or to run unit tests with PHPUnit.
config: As its name indicates, this folder allows you to group together the configuration files of the different libraries that we may have to install.
public: Corresponds to the entry point of our application. This is where we will store the public files that people can see. In the case of an API, we will have only one file
src: Gathers all the logic of our application. We will find for example entities, controllers, repositories, ... This is where we will spend most of our time.
var: Allows you to store various temporary files such as cache files or log files.
Of course, other folders may appear during the development, like the migration folder. Here is the basic structure of a Symfony project in its minimal version. Actually, there is one last folder, which is common to PHP projects. It is the
vendor folder which gathers all the packages we have installed.
Now that we know how a Symfony project is organized, we'll have to configure it. This configuration will be done by modifying the
.env folder located at the root of the project as well as the installation of several packages thanks to Symfony Flex.
Installation of global packages
To make our API work, we will have to install different libraries to configure the Doctrine ORM for example or to have at our disposal utility commands to easily create our future controllers, entities and migrations.
To do this, simply run the following dial command.
composer require orm composer require --dev maker-bundle
The installation of the package
orm actually allows you to install multiple packages at once:
migrations folder at the root of the project should be visible as well as the two folders
Finally, the file
.env has been updated to include the Doctrine configuration. We will see later how to finish the configuration of the latter.
Modification of environment variables
We are not going to directly modify the
.env file because it will contain the default variables of our application. Instead, we will use a
.env.local file which will contain only the variables that will differ from the
Thus in the
.env.local file, we will only have to fill in the variable
# .env.local DATABASE_URL="mysql://db_user:db_password@db_host:db_port/db_name"
You will only have to change the fields
db_name by the values of your choice or by the one of your database.
db_userwill have to match the username of your database with which you want to connect.
db_passwordis simply the word for that user.
db_hostis the url of your database. If the database is running locally, you can enter the ip
db_port: By default, it is port 3306.
db_nameis the name of the database we are going to create. You can choose the name of your database. For the example, we will use the name
You should end up with something like this.
# .env.local DATABASE_URL="mysql://user:firstname.lastname@example.org:3306/api"
If you are using the Docker configuration, you should have the following line:
# .env.local DATABASE_URL="mysql://root:password@database:3306/api?serverVersion=mariadb-10.7.3&charset=utf8mb4"
Creation of the database
Now that the whole project is configured, we only have to create the database before starting the development.
To do this, simply run the following command.
php bin/console doctrine:database:create
php bin/console d:d:c
We can now start developing the first bricks of our API.
In this lesson, we had the opportunity to see how to create a Symfony project thanks to the Compose commands. At the same time, we configured a Docker image so that we could get our API working properly. Finally, we installed various libraries global to the project thanks to Symfony Flex.