ZetCode

Introduction to Symfony

last modified July 5, 2020

This is an introductory Symfony tutorial. It presents the Symfony PHP framework and shows how to create simple examples. This tutorial covers Symfony version 5.

Symfony

Symfony is a set of reusable PHP components and a PHP framework for web projects. Symfony was published as free software in 2005. The original author of Symfony is Fabien Potencier. Symfony was heavily inspired by the Spring Framework.

Symfony uses several PHP open-source projects such as Doctrine object-relational mapping library, PDO database abstraction layer, PHPUnit test framework, Twig template engine, and Swift Mailer e-mail library.

Symfony has created its own components, including Symfony Dependency Injector and Symfony YAML parser.

Symfony CLI

Symfony CLI is a tool for creating and managing Symfony applications locally and on the Symfony cloud. It includes a powerful local web server to develop applications. We download the Symfony CLI from the https://symfony.com/download.

Setting up Symfony project

In order to create a Symfony 5 project, we need PHP 7.2.5 or higher (and related libraries such as php-xml or php-mcrypt) and composer. Project dependencies are written into the composer.json file.

$ symfony new symfirst

With the symfony tool, we create a new Symfony skeleton project. Symfony skeleton is an equivalent to a micro framework, where we need to install all the modules ourselvers. We decide what modules we install. This is good for learning purposes.

$ cd symfirst

Do not forget to go to the project directory.

Symfony project structure

The composer created a Symfony application structure.

$ ls -1ap --group-directories-first
./
../
bin/
config/
public/
src/
var/
vendor/
.env
.gitignore
composer.json
composer.lock
symfony.lock

The bin directory contains the console tool, which is a command-line utility to execute various types of commands. The public directory contains web files. In a Symfony skeleton application, it contains one file: index.php, which is a Symfony front controller.

Third party dependencies are stored in the vendor directory. The config directory contains configuration files. The source code is written in the src directory. The var directory contains temporary files, such as caching data.

There are also two specific hidden files: .env and .gitignore. The contents of the .env become environment variables. Environment variables are used by various tools such as ORM libraries. The .env may contain sensitive or computer specific data; therefore, it should not be committed to the repositories. The .gitignore specifies intentionally untracked files to ignore by the git tool.

Composer dependencies are defined in composer.json. The composer.lock records the exact versions that are installed so that they can be re-installed later. It ensures that everybody working on a project has the same exact versions of libraries. The symfony.lock file is the proper lock file for Symfony recipes.

Installing Symfony project dependencies

Next we will install a few project dependencies.

$ composer require maker --dev

We install the maker component, which is used to generate commands, controllers, form classes, or event subscribers.

$ composer require annotations twig

We install two additional Symfony modules. The annotations provides a way to configure your controllers with annotations. The twig allows to use Twig template engine in Symfony applications.

Symfony creating controller

Symfony controller is a PHP function that reads information from the Request object and creates and returns a Response object. The response could be an HTML page, JSON, XML, a file download, a redirect, a 404 error and so on.

$ php bin/console make:controller HelloController

With the console tool, we create a HelloController. The controller is created in src/Controller/ directory.

src/Controller/HelloController.php
<?php

namespace App\Controller;

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

class HelloController extends AbstractController
{
    /**
     * @Route("/plain", name="plain")
     */
    public function helloPlain(): Response
    {
        return new Response("Hello there", Response::HTTP_OK,
            ['content-type' => 'text/plain']);
    }
}

This is the HelloController. It is located in the src/Controller/HelloController.php file.

/**
 * @Route("/plain", name="plain")
 */
public function helloPlain()
{

A route is a map from a URL path to a controller method. The @Route annotation maps the /plain URL path to the helloPlain() function.

return new Response("Hello there",  Response::HTTP_OK,
  ['content-type' => 'text/plain']);

The function returns a Response object. A Response object holds all the information that needs to be sent back to the client from a given request. The constructor takes up to three arguments: the response content, the status code, and an array of HTTP headers. The default status code is Response::HTTP_OK and content type text/html.

$ symfony serve

We start a local web development server with symfony serve.

$ curl 127.0.0.1:8000/plain
Hello there

We issue a GET request to the plain route and see the text response.

Symfony with Twig template

When we issused composer require twig command, a Twig template engine was installed to the project directory. Also a templates directory was created. In that directory we place our template files. The template files have html.twig extension.

src/Controller/HelloController.php
<?php

namespace App\Controller;

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

class HelloController extends AbstractController
{
    /**
     * @Route("/plain", name="plain")
     */
    public function helloPlain(): Response
    {
        return new Response("Hello there", Response::HTTP_OK,
            ['content-type' => 'text/plain']);
    }

    /**
     * @Route("/twig", name="twig")
     */
    public function helloTwig(): Response
    {
        $message = "Hello from Twig";
        return $this->render('hello/index.html.twig', ["message" => $message]);
    }
}

We have updated the HelloController.php file; we have added a new route. This time the function renders a Twig template.

/**
 * @Route("/twig", name="twig")
 */
public function helloTwig(): Response
{

The helloTwig() function is mapped to the twig path.

$message = "Hello from Twig";
return $this->render('hello/index.html.twig', ["message" => $message]);

Twig renders the 'hello/index.html.twig file, located in the templates directory. The render() method also accepts data; in our case it is a message variable. The template engine merges data with a HTML structure.

templates/hello/index.html.twig
{% extends 'base.html.twig' %}

{% block title %}Plain message{% endblock %}

{% block body %}
    {{ message }}
{% endblock %}

This is the Twig template file.

{% extends 'base.html.twig' %}

The template inherits from the base.html.twig file, which has base markup that will be shared.

{{ message }}

The {{ }} is a special Twig syntax which shows the contents of the variable.

templates/base.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}{% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

The base.html.twig template contains code that is shared by other template files. It defines blocks that will be replaced in children templates.

$ curl 127.0.0.1:8000/twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Plain message</title>
      </head>
    <body>
          Hello from Twig
    </body>
</html>

We get this HTML output when we connect to the twig path.

In this tutorial we have introduced the Symfony framework.

List all Symfony tutorials.