This tutorial is created from an UDEMY course (https://www.udemy.com/course/creer-4-applications-avec-symfony-v4-evolution-progressive/)

To run Symfony you will need 2 things:

  • Symfony
  • Composer

You can download Symfony from the official website: https://symfony.com/download

Composer is a package manager like npm for node.js
https://getcomposer.org/download/

Symfony Create New Project

To create a new project using symfony you can take 2 roads:

if you want to install a traditional web application:

symfony new --full my_project

If you cant to buyild a microservice, a console application, or API:

symfony new my_project

When installing a full project you are installing a lot of more packages that you usually need to start a FULL web project, while if you start a non-full new project you will need to install those components later by yourself.

The installation will install all required files and folders but also all packages needed. And for that reason, the installation takes a little time.
You will see that your empty project will be around 50 MB.

Let’s Create our First Page

First you need to know that symfony comes with a set of Binary software that let you do a lot of stuff! And that is exactly what we are going to do! We are going to create a new page calling the software(binary) that symfony is giving us! On the terminal :

 php bin/console make:controller controller_name

We will create a controller that will be in charge of handling some Characters

php bin/console make:controller characterController

And this is the result

As you can see, the binary have generated 2 files:
CharacterController.php and index.html.twig in 2 different folders.

Let’s analyze our controller.

What contains our controller?

It contains the class of our controller (that extends “AbstratctController”)

It contains a name space

It contains two use statements (I think is like an include) to include the files that contains the class we will need and use (“AbstractController” and “Route”)

Inside the class CharacterController we can find the function index()!
This function will be launched when we are going to call the route. What route? Well as I told you already don’t look into the code to have your answer, look at comments:

/**
 * @Route("/character", name="character")
 */

This code (even if this is comments), will indicate that the function will be executed when the route “/character” will be called

Let’s dive into our function index()
We have a return statement that will return the result of $this->render(twig file)

So this function will call the render function of a twig page and get the result to the page.

We can now create another route easily (using the annotation) and adding another function (with another name).
Then we create another twig HTML page, and we have another page in our system.

ROUTING OF NAMING???

This is another important concept that Symfony introduces!
Let’s imagine that you have created a route called /persons that list all the students of a school…
Now you are midway finishing your job, and you notice that you should change your route to /students!

The problem is that you have a lot of links that you have created that link to the route /person and you should change every one of those links to the new route.

This is tedious and too long, so Symfony created the concept of names:

  /**
     * @Route("/students", name="allStudents")
     */

Using twig you should not put the link directly to the route but use this code:

<a href = "{{ path("allStudents") }}">Students</a>

Using this method, we can change the rout of our page without changing all the links, because the system will find your route for you using the name.

PASSING DATA VIA URL

To send data to our route, you can do this:

 @Route("/character/{{id}}", name="show_character")

To add this information using TWIG you can add another argument to the path() function :

<a href="{{ path('show_character',{'id': player.id}) }}">

As you can see we pass a single JSON object to the function! And we use the correct name to pass the info.

Now to catch the info, sent via the routing, you just pass them in your function:

/*
 * @Route("/character/{{id}}", name="show_character")
 */
public function show_charatceter($id){} 

SEND DATA TO THE TEMPLATE

We can send data from the controller to the template, to do so, let’s see the code of our controller.

return $this->render('character/index.html.twig', [
            'controller_name' => 'CharacterController',
        ]);

Inside the render function, we can pass an array that the template can understand and so print the right info. In this case, we are passing to the template the name of the controller called. But if you want you can pass other things. The template will receive the data and you can print it simply by doing {{controller_name}}

This is the base of the MVC because we get the info from the controller and we send it to the View.

The also good thing is that we can send array values that will be transfomed in jsons so you can easily send:

["name"=>"Simone", "age"=>34, "skills" => ["force" =>10, "strategy" => 3]]

And in our template we can do:

Name : {{name}} <br>
Age : {{age}} <br>
Force : {{skills.force}}
Strategy : {{skills.strategy}}

ROUTING ENTITY INJECTION

Let’s imagine that you want to show a specific object in your web site: you create a controller for this action:

/**
* @Route("/filiere/{uid}", name="filiere_modification")
*/
public function filiereModification($uid): Response
{
  $filiere = /*here the code to collect info from db using the $uid variable */
  return $this->render('filiere/modificationFiliere.html.twig', [
  'filiere'=>$filiere
  ]);
}

So, we crate the route, we load the infos from db and then we pass them to the view.

There is a faster way to do this:

/**  
* @Route("/filiere/{uid}", name="filiere_modification")  
*/ 

public function filiereModification(Filiere $filiere): Response 
{
  return $this->render('filiere/modificationFiliere.html.twig', [
             'filiere'=>$filiere
         ]);
}

How does this work ? You specify the ID of the element you want to retrieve from the database in your url (using {id} ), since as parameter you have (Filiere $filiere) Symfony understand that that {id} must be linked to the entity Filiere, he automatically go to the database and look for an ID of ( what you have passed ).

This way you dont have to create the code to look for the entity yourself inside the database, and development is faster.

But, is ID the default? What if you want to use another field to research your entity?

Well, you just need to replace the {id} parmeter with the name of the column that you want to use ex: {uid}

What if you have more than one result from looking for an entity this way?

In every case, only one entity is returned, the first match that the database return !