Getting Started | Building a Shopping Cart with Symfony
Tags: php, symfony, tutorial, setup
Published: 2020-12-21 12:52:13

* [Requirements](#requirements)
* [Setting up the Project](#setting-up-project)
 * [Creating the project](#creating-project)
 * [Launching the Local Web Server](#launch-web-server)
 * [Installing dependencies](#installing-dependencies)
* [Setting up the Database](#setting-up-database)
 * [Adding MySQL to Docker Compose](#adding-mysql-to-docker-compose)
 * [Starting Docker Compose](#starting-docker-compose)
 * [Changing the Environment Variable](#changing-environment-variable)
 * [Creating the Database](#create-database)
* [Creating the Home Page](#creating-home-page)
 * [Creating the Home Controller](#home-controller)
 * [Updating the base Layout](#updating-base-layout)

------

Before coding, we need to set up the working environment and make sure that everything is working well.

Requirements <a name="requirements"></a>
-------------
- PHP 7.2.5+
- [Composer](https://getcomposer.org/download)
- [Symfony CLI](https://symfony.com/download)
- [Docker & Docker compose](https://docs.docker.com/get-docker)

Setting up the Project <a name="setting-up-project"></a>
----------------------

### Creating the project
Create a new Symfony project using the Symfony CLI tool:

```
$ symfony new happy-shop
```

### Launching the Local Web Server <a name="launch-local-web-server"></a>
From the project directory, start the web server in the background:

```
$ cd happy-shop
$ symfony server:start -d
```

The server started on the port 8000. Open the website http://localhost:8000 in a browser.

![1_93VMZOExzO1MDR-dYEMbhg](https://dev-to-uploads.s3.amazonaws.com/i/mo9e75op8oc7j4sa2y1h.png)

### Installing dependencies <a name="installing-dependencies"></a>

We will need some dependencies for our project. To install these packages, we will use the Symfony CLI:

```
$ symfony composer req form validator annotations orm twig
```

- [Form](https://symfony.com/doc/current/components/form.html): we will need to build forms for the shopping cart,
- [Validator](https://symfony.com/doc/current/validation.html): it will allow us to validate the data models,
- [Annotations](https://symfony.com/doc/current/routing.html): we will use the annotations format for the configuration of the project,
- [ORM](https://www.doctrine-project.org/): known as Doctrine, it will help us to persist entities in a database,
- [Twig](https://twig.symfony.com/): all templates will be created using Twig.

#### Dependencies for developing

The following components will be installed only for developing the project:

```
$ symfony composer req profiler maker orm-fixtures phpunit browser-kit dama/doctrine-test-bundle --dev
```

- [Profiler](https://symfony.com/doc/current/profiler.html): useful to debug and see details of all requests we will execute,
- [Maker](https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html): it helps you to generate a lot of different classes. We will use it all the time during the project,
- [Fixtures](https://symfony.com/doc/current/bundles/DoctrineFixturesBundle/index.html): it will be used to load fake products to help us developing the shopping cart,
- [PHPUnit](https://phpunit.readthedocs.io/): essential for writing tests,
- [BrowserKit](https://symfony.com/doc/current/components/browser_kit.html): to test with a Client service that simulates a browser,
- [DoctrineTestBundle](https://github.com/dmaicher/doctrine-test-bundle): provides a listener to reset the database between tests.

Setting up the Database <a name="setting-up-database"></a>
-----------------------
We will need to persist entities in permanent storage. We will use the MySQL database.

### Adding MySQL to Docker Compose <a name="adding-mysql-docker-composer"></a>

From the project directory, create a `docker-compose.yaml` file:

```yaml
# docker-compose.yaml
version: '3'
services:
  database:
    image: library/mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: happy
      MYSQL_DATABASE: happy_shop
    ports:
      - 3306:3306
```

This will install the MySQL server at version 8.0 and configure some environment variables that control the database name and credentials. The exposed port will help us access the database from Symfony.

### Starting Docker Compose <a name="starting-docker-compose"></a>
Start Docker Compose in the background:

```
$ docker-compose up -d
```

### Changing the Environment Variable <a name="changing-environment-variable"></a>
Set up the default DATABASE_URL value to use MySQL:

```
# .env
###> doctrine/doctrine-bundle ###
DATABASE_URL="mysql://root:happy@127.0.0.1:3306/happy_shop?serverVersion=8.0"
###< doctrine/doctrine-bundle ###
```

### Creating the Database <a name="create-database">

To create the database, run the following command:

```
$ bin/console doctrine:database:create --if-not-exists
```

Creating the Home Page <a name="creating-home-page"></a>
---------------------------

### Creating the Home Controller <a name="home-controller"></a>

Create the `HomeController` controller via the Maker:

```
$ symfony console make:controller HomeController
```

The command creates a `HomeController` class under the `src/Controller/` directory and a template file to `templates/home/index.html.twig`.

In the `HomeController` class, define a route to make it match the homepage:

```php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class HomeController extends AbstractController
{
    /**
     * @Route("/", name="home")
     */
    public function index(): Response
    {
        return $this->render('home/index.html.twig', [
            'controller_name' => 'HomeController',
        ]);
    }
}
```

You already can go to the homepage http://localhost:8000. Try it!

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/3haqbsld0rupalshfffm.png)

### Updating the base Layout <a name="updating-base-layout"></a>
All templates will be depending on the base layout to share common elements, like the meta, title, header, and more.

We will use Bootstrap for designing the pages of the project but please note that the design is not the goal of this project so we will just make it functional.

```twig
{# templates/base.html.twig #}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>{% block title %}Happy Shop{% endblock %}</title>
    {% block stylesheets %}
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
              integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
              crossorigin="anonymous">
    {% endblock %}
</head>
<body>
{% block header %}
    <nav class="navbar navbar-dark bg-dark sticky-top">
        <a href="{{ path('home') }}" class="navbar-brand">
            Happy Shop
        </a>
    </nav>
{% endblock %}

{% block body %}{% endblock %}
</body>
</html>
```

This template defines the base HTML skeleton. We've defined the title, header, and body blocks. We also set the viewport to make the app responsive.

To see the result, let's go back to the homepage http://localhost:8000:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m7s2ulafs0tdju949upo.png)

We are ready! Let's manage products to the next step.