• 30 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 13/05/2019

Mon premier « Hello World ! » avec Symfony

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

L'objectif de ce chapitre est de créer de toutes pièces notre première page avec Symfony : une simple page blanche comprenant un « Hello World ! ». Nous allons donc créer tous les éléments indispensables pour concevoir une telle page.

Nous allons avoir une vue d'ensemble de tous les acteurs qui interviennent dans la création d'une page : routeur, contrôleur et template. Pour cela, tous les détails ne seront pas expliqués afin qu'on se concentre sur l'essentiel : la façon dont ils se coordonnent. Vous devrez attendre les prochains chapitres pour étudier un à un ces trois acteurs, patience donc !

Ne bloquez donc pas sur un point si vous ne comprenez pas tout, forcez-vous juste à comprendre l'ensemble. À la fin du chapitre, vous aurez une vision globale de la création d'une page et l'objectif sera atteint.

Bonne lecture !

Créons notre route

Le routeur (ou router) ? Une route ?

Objectif

L'objectif du routeur est de faire la correspondance entre une URL et des paramètres.

Par exemple, nous pourrions avoir une route qui dit « Lorsque l'URL appelée est /hello-world, alors le contrôleur à exécuter est Advert  (pour Advertisement en anglais, Annonce en français). ». Le contrôleur à exécuter est un paramètre obligatoire de la route, mais il peut bien sûr y en avoir d'autres.

Le rôle du routeur est donc de trouver la bonne route qui correspond à l'URL appelée, et de retourner les paramètres de cette route.

La figure suivante synthétise le fonctionnement du routeur.

Fonctionnement du routeur
Fonctionnement du routeur

Nous ne toucherons ni au noyau, ni au routeur : nous nous occuperons juste des routes.

Créons notre fichier de routes

Rappelez-vous, notre code va se trouver dans le répertoire  /src , et notre configuration dans le répertoire  /config . En l'occurrence, les routes de notre application sont de la configuration, il faut donc ouvrir le répertoire  /config .

Les routes se définissent dans un simple fichier texte, que Symfony a déjà créé pour nous, il s'agit de  /config/routes.yaml . Ouvrez ce fichier, et ajoutez cette route à la place de celle qui est commentée :

# config/routes.yaml

hello_the_world:
    path:       /hello-world
    controller: App\Controller\AdvertController::index

Vous venez de créer votre première route !

Essayons de comprendre rapidement cette route :

  • hello_the_world est le nom de la route. Il est assez arbitraire, et vous permet juste de vous y retrouver par la suite. La seule contrainte est qu'il soit unique.

  • pathcorrespond à l'URL à laquelle nous souhaitons que notre « Hello World ! » soit accessible. C'est ce qui permet à la route de dire : « Cette URL est pour moi, je prends. »

  • controllercorrespond à un paramètre de la route. La valeur correspond à l'action (ici, « index », un nom de méthode) et au contrôleur (ici, « App\Controller\AdvertController », un nom de classe) que l'on veut exécuter. Un contrôleur peut contenir plusieurs actions, c'est-à-dire plusieurs pages.

Ne vous inquiétez pas, un chapitre complet est consacré au routeur et vous permettra de jouer avec. Pour l'instant ce fichier nous permet juste d'avancer.

Comment Symfony est-il au courant de cette route ?

En effet, nous venons d'ajouter quelques lignes dans un fichier de configuration, perdu dans le répertoire  /config . Comment fait-il pour savoir que cette route est ici ? C'est dans le fichier  src/Kernel.php  que cela se passe. Ce fichier n'est pas le noyau de Symfony à proprement parler, il en hérite seulement.

Par contre, c'est dans ce fichier que nous indiquons au noyau plusieurs informations importantes, comme où regarder pour trouver nos routes ! Ouvrez le fichier, il s'agit de la méthode  configureRoutes  . Sans comprendre exactement le code, on peut voir que le noyau charge notre fichier  /config/routes.yml  , mais aussi tout fichier dans le répertoire  /config/routes  (nous n'en avons pas encore pour le moment).

Et voilà, il n'y a plus qu'à créer le fameux contrôleur App\Controller\AdvertController  ainsi que sa méthode index !

Créons notre contrôleur

Le rôle du contrôleur

Rappelez-vous ce que nous avons dit sur le MVC :

  • Le contrôleur est la « glu » de notre site ;

  • Il « utilise » tous les autres composants (base de données, formulaires, templates, etc.) pour générer la réponse suite à notre requête ;

  • C'est ici que résidera toute la logique de notre site : si l'utilisateur est connecté et qu'il a le droit de modifier cet article, alors j'affiche le formulaire d'édition des articles de blog.

Créons notre contrôleur

1. Le fichier de notre contrôleur Advert

Dans une application Symfony, les contrôleurs se trouvent dans le répertoire /src/Controller. Rappelez-vous : dans la route, on a dit qu'il fallait faire appel au contrôleur nommé « App\Controller\AdvertController ». 

Crérez donc le fichier /src/Controller/AdvertController.php et mettez-y le code suivant :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

class AdvertController
{
  public function index()
  {
    $content = "Notre propre Hello World !"

    return new Response($content);
  }
}

Surprise : allez voir sur http://localhost/mooc-symfony4/public/index.php/hello-world ! Notre propre Hello World s'affiche.

Maintenant, essayons de comprendre rapidement ce fichier :

  • Ligne 4 : on se place dans le namespace des contrôleurs de notre application. Suivez la structure des répertoires dans lequel se trouve le contrôleur.

  • Ligne 6 : notre contrôleur va utiliser l'objet Response, il faut donc le définir grâce au use.

  • Ligne 8 : le nom de notre contrôleur respecte le nom du fichier pour que l'autoload fonctionne.

  • Ligne 10 : on définit la méthode index(), ce que mentionne la route.

  • Ligne 12 : on définit un contenu pour notre page, ici un texte simple, sans HTML.

  • Ligne 14 : on crée une réponse. L'argument de l'objet Response est le contenu de la page que vous envoyez au visiteur, ici « Notre propre Hello World ! ». Puis on retourne cet objet.

Bon, certes, le rendu n'est pas très joli, mais au moins nous avons atteint l'objectif d'afficher nous-mêmes un « Hello World ! ».

Mais écrire le contenu de sa page de cette manière dans le contrôleur, ce n'est pas très pratique, et en plus de cela on ne respecte pas le modèle MVC. Utilisons donc les templates (ou vues) !

Créons notre template Twig

Les templates avec Twig

Savez-vous ce qu'est un moteur de templates ? C'est un script qui permet d'utiliser des templates, c'est-à-dire des fichiers qui ont pour but d'afficher le contenu de votre page HTML de façon dynamique, mais sans PHP. Comment ? Avec leur langage à eux. Chaque moteur a son propre langage.

Avec Symfony, nous allons employer le moteur Twig. Voici un exemple de comparaison entre un template simple en PHP (premier code) et un template en « langage Twig » (deuxième code).

<!DOCTYPE html>
<html>
  <head>
    <title>Bienvenue dans Symfony2 !</title>
  </head>
  <body>
    <h1><?php echo $titre_page; ?></h1>

    <ul id="navigation">
      <?php foreach ($navigation as $item) { ?>
        <li>
          <a href="<?php echo $item->getHref(); ?>"><?php echo $item->getTitre(); ?></a>
        </li>
      <?php } ?>
    </ul>
  </body>
</html>
<!DOCTYPE html>
<html>
  <head>
        <title>Bienvenue dans Symfony2 !</title>
  </head>
  <body>
    <h1>{{ titre_page }}</h1>

    <ul id="navigation">
      {% for item in navigation %}
        <li><a href="{{ item.href }}">{{ item.titre }}</a></li>
      {% endfor %}
    </ul>
  </body>
</html>

Ils se ressemblent, soyons d'accord. Mais celui réalisé avec Twig est bien plus facile à lire ! Pour afficher une variable, vous écrivez juste {{ ma_var }} au lieu de <?php echo $ma_var; ?>.

Le but en fait est de faciliter le travail de votre designer. Un designer ne connaît pas forcément le PHP, ni forcément Twig d'ailleurs. Mais Twig est très rapide à prendre en main, plus rapide à écrire et à lire, et il dispose aussi de fonctionnalités très intéressantes. Par exemple, imaginons que votre designer veuille mettre les titres en lettres majuscules (COMME CECI). Il lui suffit d'écrire : {{ titre|upper }}, où titre est la variable qui contient le titre d'un article de blog par exemple. C'est plus joli que <?php echo strtoupper($titre); ?>, non ?

Nous verrons dans le chapitre dédié à Twig les nombreuses fonctionnalités que le moteur vous propose et qui vont vous faciliter la vie. En attendant, nous devons avancer sur notre « Hello World ! ».

Utiliser Twig avec Symfony

Comment utiliser un template Twig depuis notre contrôleur, au lieu d'afficher notre texte tout simple ?

1. Installons la recette Twig

Pour utiliser le moteur de template Twig, il faut d'abord l'installer. En effet, Twig est indépendant de Symfony, et n'est donc pas livré avec. Certaines applications n'utilisent pas de templates, par exemple si ce sont des API ne retournant que du contenu au format JSON ou XML.

Comme nous l'avions fait avec Monolog, il faut exécuter la commande  composer require twig  .

$ composer require twig

Restricting packages listed in "symfony/symfony" to "4.1.*"
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Restricting packages listed in "symfony/symfony" to "4.1.*"

Prefetching 2 packages
 - Downloading (100%)

Package operations: 3 installs, 0 updates, 0 removals
 - Installing twig/twig (v2.5.0): Loading from cache
 - Installing symfony/twig-bridge (v4.1.6): Loading from cache
 - Installing symfony/twig-bundle (v4.1.6): Loading from cache
Writing lock file
Generating autoload files
Symfony operations: 1 recipe (4f28603fa6e02bc04731543422e719e3)
 - Configuring symfony/twig-bundle (>=3.3): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

Composer a donc installé la bibliothèque Twig, le bundle associé pour l'intégrer dans une application Symfony, et a également configuré ce bundle, notamment dans le fichier  /config/packages/twig.yaml .

Ouvrez ce fichier, et notez le paramètre  default_path , dont la valeur est  /templates (%kernel.project_dir%  étant le répertoire racine de notre projet). C'est dans ce répertoire que nous allons mettre nos templates.

1. Créons le fichier du template

Créez donc le fichier /templates/Advert/index.html.twig.

Je vous propose de découper ce nom Advert/index.html.twig :

  • Advert est le nom du répertoire. Nous l'avons appelé comme notre contrôleur afin de nous y retrouver (ce n'est pas une obligation, mais c'est fortement recommandé, ainsi toutes les actions du contrôleur Advert utiliserons des vues dans ce répertoire Advert).

  • index est le nom de notre template qui est aussi le nom de la méthode de notre contrôleur (idem, rien d'obligatoire, mais très recommandé).

  • html correspond au format du contenu de notre template. Ici, nous allons y mettre du code HTML, mais vous serez amené à vouloir y mettre du XML ou autre : vous changerez donc cette extension. Cela permet de mieux s'y retrouver.

  • twig est le format de notre template. Ici, nous utilisons Twig comme moteur de templates, mais il est toujours possible d'utiliser des templates PHP.

Revenez à notre template et mettez ce code à l'intérieur :

{# templates/Advert/index.html.twig #}

<!DOCTYPE html>
<html>
<head>
  <title>Bienvenue sur ma première page avec OpenClassrooms !</title>
  <meta charset="UTF-8">
</head>
<body>
  <h1>Hello World !</h1>
  <p>
    Le Hello World est un grand classique en programmation.
    Il signifie énormément, car cela veut dire que vous avez
    réussi à exécuter le programme pour accomplir une tâche simple :
    afficher ce hello world !
  </p>
</body>
</html>

Dans ce template, nous n'avons utilisé ni variable, ni structure Twig. En fait, c'est un fichier contenant uniquement du code HTML pur !

3. Appelons ce template depuis le contrôleur

Il ne reste plus qu'à appeler ce template. C'est le rôle du contrôleur, c'est donc au sein de la méthode index() que nous allons intervenir.

Pour accéder aux méthodes de gestion des templates, nous allons "injecter" l'objet Twig qui nous permettra de manipuler les templates. Ensuite, la méthode concrète que nous utilisons pour récupérer le contenu d'un template est la méthode $twig->render(). Cette méthode prend en paramètre le nom du template et retourne le contenu du template. Voici le contrôleur modifié en conséquence :

<?php
// src/Controller/AdvertController.php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;

class AdvertController
{
  public function index(Environment $twig)
  {
    $content = $twig->render('Advert/index.html.twig');

    return new Response($content);
  }
}

Nous avons modifié la ligne 11 pour y injecter l'objet Twig, ainsi que la ligne 13 pour récupérer le contenu du template.

Le chemin à renseigner dans la méthode  render  est le chemin relatif par rapport à notre répertoire de base  /template . Ainsi, pour accéder à  /templates/Advert/index.html.twig , il faut renseigner  Advert/index.html.twig . 

function index(Environment $twig)  ? Qu'est-ce que c'est exactement ?

Très Bonne question ! Cette syntaxe permet "d'injecter" un objet dans les méthodes d'un contrôleur. Ici, cet objet  Twig\Environment  permet de manipuler les templates Twig, mais il existe bien d'autres objets que nous aborderons tout au long de ce cours !

Ces objets, appelés services, sont une fonctionnalité phare de Symfony, que nous étudions très en détails dans la prochaine partie de ce cours. Je vais vous demander un peu de patience, en attendant vous pouvez les utiliser sans forcément comprendre d'où ils viennent.

Maintenant, retournez sur la page http://localhost/mooc-symfony4/public/index.php/hello-world et profitez !

Notre vue Hello World s'affiche bien !
Notre vue Hello World s'affiche bien !

Vous voulez vous amuser un peu avec les variables Twig ? Modifiez le contrôleur pour rajouter un deuxième argument à la méthode render(), un tableau contenant le nom des variables (ici, "name") et leur valeur (ici, "winzou") :

<?php
$content = $twig->render('Advert/index.html.twig', ['name' => 'winzou']);

Puis, modifiez votre template en remplaçant la balise <h1> par la suivante :

<h1>Hello {{ name }} !</h1>

C'est tout ! Rechargez la page. Bonjour à vous également. :) Je n'en dis pas plus pour le moment, on verra plus en détail le passage de variables dans le chapitre dédié à Twig bien évidemment.

Notre objectif : créer une plateforme d'annonces

Le fil conducteur

Comme je vous l'ai déjà annoncé, nous construirons une plateforme d'annonces tout au long de ce cours. Cela me permet d'utiliser des exemples cohérents entre eux et de vous montrer comment construire un tel site de toutes pièces. Bien sûr, libre à vous d'adapter les exemples au projet que vous souhaitez mener, je vous y encourage, même !

Le choix de ce site permet que l'on se comprenne bien : vous savez déjà ce qu'est une plateforme d'annonces (leboncoin, eBay, etc.), vous comprendrez donc tous les exemples.

Notre plateforme

La plateforme que nous allons créer est très simple. En voici les grandes lignes :

  • Nous aurons des annonces (advert en anglais) de mission : développement d'un site internet, création d'une maquette, intégration HTML, etc. ;

  • Nous pourrons consulter, créer, modifier et rechercher des annonces ;

  • À chaque annonce, nous pourrons lier une image d'illustration ;

  • À chaque annonce, nous pourrons lier plusieurs candidatures (application en anglais) ;

  • Nous aurons plusieurs catégories (Développement, Graphisme, etc.) qui seront liées aux annonces. Nous pourrons créer, modifier et supprimer ces catégories ;

  • À chaque annonce, nous pourrons enfin lier des niveaux de compétence requis (Expert en PHP, maîtrise de Photoshop, etc.).

  • Au début, nous n'aurons pas de système de gestion des utilisateurs : nous devrons saisir notre nom lorsque nous rédigerons une annonce. Puis, nous rajouterons la couche utilisateur.

Rentrons un peu dans Symfony

Une barre d'outil ?

Je vous avoue qu'il serait intéressant de savoir, sur une page donnée, quels sont les route, contrôleur et template utilisés. Pour l'instant nous n'avons qu'un seul de chaque, mais plus tard cela pourrait nous faciliter la tâche.

Heureusement, Symfony contient une brique qui nous permet de répondre à ce besoin ! Installez la recette (encore une !)  debug , à l'aide de Composer :   composer require debug .

Encore une fois, Composer (grâce à Flex) a installé et configuré plusieurs bundles. Actualisez notre page de Hello World, et voyez la petite barre apparue en bas de page.

Notez la barre d'outil en bas
Notez la barre d'outil en bas

Cette barre d'outil n'est pas apparue par magie. Il y a plusieurs mécanismes derrière.

Premièrement, elle n'apparaît que sur les pages qui contiennent la balise fermante  </body> . Cela permet d'ajouter cette barre seulement aux pages HTML, et non aux autres pages que vous pourriez retourner. Nous parlerons du mécanisme qui permet de faire cela en seconde partie de ce cours.

Ensuite, cette barre d'outil est cliquable, essayez ! Cliquez sur le nom de la route par exemple, vous verrez des informations sur la requête HTTP, la réponse, etc. Je ne vous en dis pas plus sur cette partie, nous aurons l'occasion de nous y repencher. Notez cependant que pour afficher cette page... il faut bien une route et un contrôleur ! Lors de la configuration de la recette  debug , Flex a ajouté le fichier de route  /config/routes/dev/web_profiler.yaml . C'est dans ce fichier que sont référencées les routes utilisés par la barre d'outil.

Et comme ce fichier de routes est dans le sous-répertoire  dev , ces routes (et donc la barre d'outil toute entière) ne sont disponibles qu'en environnement de développement. Encore heureux, nous ne voulons pas d'une telle barre pour nos visiteurs en production !

Le cache

Symfony, pour nous offrir autant de fonctionnalités et être si rapide, utilise beaucoup son cache.

Le cache est constitué de fichiers PHP prêts à être exécutés, contenant tout le nécessaire pour faire tourner Symfony sous une forme plus rapide. Pensez par exemple à la configuration dans les fichiers YAML : quand Symfony génère une page, il va compiler cette configuration dans un tableau PHP natif (un array ), ce qui sera bien plus rapide à charger la fois suivante.

Or après certaines modifications, le cache peut ne plus être à jour, ce qui peut entrainer des erreurs. Deux cas de figure :

  • En mode « prod », c'est simple, Symfony ne regénère jamais le cache. Cela lui permet de ne faire aucune vérification sur la validité du cache (ce qui prend du temps), et de servir les pages très rapidement à vos visiteurs. La solution : vider le cache à la main à chaque fois que vous faites des changements. Cela se fait grâce à la commande php bin/console cache:clear --env=prod.

  • En mode « dev », c'est plus simple. Lorsque vous modifiez votre code, Symfony reconstruit une bonne partie du cache à la prochaine page que vous chargez. Donc pas forcément besoin de vider le cache. Seulement, comme il ne reconstruit pas tout, il peut parfois apparaître des bugs un peu étranges. Dans ce cas, un petit php bin/console cache:clear résout le problème en trois secondes !

Pour conclure

Et voilà, nous avons créé une page de A à Z ! Voici plusieurs remarques sur ce chapitre.

D'abord, ne vous affolez pas si vous n'avez pas tout compris. Le but de ce chapitre était de vous donner une vision globale d'une page Symfony. Vous avez des notions de routes, de contrôleurs et de templates : vous savez presque tout ! Il ne reste plus qu'à approfondir chacune de ces notions, ce que nous ferons dès le prochain chapitre.

Ensuite, sachez que tout n'est pas à refaire lorsque vous créez une deuxième page. Je vous invite là, maintenant, à créer une page /byebye-world et voyez si vous y arrivez. Dans le cas contraire, relisez ce chapitre, puis si vous ne trouvez pas votre erreur, n'hésitez pas à poser votre question sur le forum PHP, d'autres personnes qui sont passés par là seront ravis de vous aider. :)

Allez, préparez-vous pour la suite, les choses sérieuses commencent !

En résumé

  • Le rôle du routeur est de déterminer quel route utiliser pour la requête courante.

  • Le rôle d'une route est d'associer une URL à une action du contrôleur.

  • Le rôle du contrôleur est de retourner au noyau un objet Response, qui contient la réponse HTTP à envoyer à l'internaute (page HTML ou redirection).

  • Le rôle des vues est de mettre en forme les données que le contrôleur lui donne, afin de construire une page HTML, un flux RSS, un e-mail, etc.

  • Le code du cours tel qu'il doit être à ce stade est disponible sur la branche iteration-3 du dépôt Github.

Exemple de certificat de réussite
Exemple de certificat de réussite