• 30 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

Ce cours existe en livre papier.

course.header.alt.is_certifying

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Mis à jour le 04/09/2017

Mon premier « Hello World ! » avec Symfony2

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 Symfony2 : 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

Nous travaillons dans notre bundle OCPlatformBundle, placez-vous donc dans son répertoire : src/OC/PlatformBundle.

Pour créer une page, il faut d'abord définir l'URL à laquelle elle sera accessible. Pour cela, il faut créer la route de cette page.

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

Comme je l'ai dit, nous ne toucherons ni au noyau, ni au routeur : nous nous occuperons juste des routes.

1. Créons notre fichier de routes

Les routes se définissent dans un simple fichier texte, que Symfony2 a déjà généré pour notre OCPlatformBundle. Usuellement, on nomme ce fichier Resources/config/routing.yml dans le répertoire du bundle. Ouvrez le fichier, et ajoutez cette route à la suite de celle qui existe déjà :

# src/OC/PlatformBundle/Resources/config/routing.yml

hello_the_world:
    path:     /hello-world
    defaults: { _controller: OCPlatformBundle:Advert: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.

  • path correspond à 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. »

  • defaults correspond aux paramètres de la route, dont :

    • _controller, qui correspond à l'action (ici, « index ») que l'on veut exécuter et au contrôleur (ici, « Advert ») que l'on va appeler (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.
Mais avant d'aller plus loin, penchons-nous sur la valeur que l'on a donnée à _controller : « OCPlatformBundle:Advert:index ». Cette valeur se découpe en suivant les deux-points (« : ») :

  • « OCPlatformBundle » est le nom de notre bundle, celui dans lequel Symfony2 ira chercher le contrôleur.

  • « Advert » est le nom du contrôleur à ouvrir. En terme de fichier, cela correspond à Controller/AdvertController.php dans le répertoire du bundle. Dans notre cas, nous avons src/OC/PlatformBundle/Controller/AdvertController.php comme chemin absolu.

  • « index » est le nom de la méthode à exécuter au sein du contrôleur.

2. Informons Symfony2 que nous avons des routes pour lui

Inutile d'informer le Routeur que nous avons une nouvelle route pour lui, il le sait déjà ! Rappelez-vous, au chapitre précédent nous avons vu que le fichier de routes de notre bundle est déjà inclus dans la configuration générale (grâce au fichier app/config/routing.yml. Il n'y a donc rien à faire de particulier ici.

En fait, on aurait pu ajouter notre route hello_the_world directement dans ce fichier app/config/routing.yml. Cela aurait fonctionné et cela aurait été plutôt rapide. Mais c'est oublier notre découpage en bundles ! En effet, cette route concerne le bundle de notre plateforme, elle doit donc se trouver dans notre bundle et pas ailleurs. N'oubliez jamais ce principe.

Cela permet à notre bundle d'être indépendant : si plus tard nous ajoutons, modifions ou supprimons des routes dans notre bundle, nous ne toucherons qu'au fichier src/OC/PlatformBundle/Resources/config/routing.yml au lieu de app/config/routing.yml. ;)

Et voilà, il n'y a plus qu'à créer le fameux contrôleur Advert  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 un bundle, les contrôleurs se trouvent dans le répertoire Controller du bundle. Rappelez-vous : dans la route, on a dit qu'il fallait faire appel au contrôleur nommé « Advert ». Le nom des fichiers des contrôleurs doit respecter une convention très simple : il doit commencer par le nom du contrôleur, ici « Advert », suivi du suffixe « Controller ». Au final, on doit donc créer le fichier src/OC/PlatformBundle/Controller/AdvertController.php.

Même si Symfony2 a déjà créé un contrôleur DefaultController pour nous, ce n'est qu'un exemple, on va utiliser le nôtre. Ouvrez donc notre AdvertController.php et mettez-y le code suivant :

<?php

// src/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class AdvertController
{
    public function indexAction()
    {
        return new Response("Hello World !");
    }
}

Surprise : allez voir sur http://localhost/Symfony/web/app_dev.php/hello-world ! Même bundle, mais contrôleur différent, on en fait des choses !

Le Hello World s'affiche !
Le Hello World s'affiche !

Maintenant, essayons de comprendre rapidement ce fichier :

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

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

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

  • Ligne 11 : on définit la méthode indexAction(). N'oubliez pas de mettre le suffixe Action derrière le nom de la méthode.

  • Ligne 13 : on crée une réponse toute simple. L'argument de l'objet Response est le contenu de la page que vous envoyez au visiteur, ici « 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 ! ».

Pourquoi indexAction() ? Je n'ai pas suivi là.

En effet, il faut savoir que le nom des méthodes des contrôleurs doit respecter une convention. Lorsque, dans la route, on parle de l'action « index », dans le contrôleur on doit définir la méthode indexAction(), c'est-à-dire le nom de l'action suivi du suffixe « Action », tout simplement. Il n'y a pas tellement à réfléchir, c'est une simple convention pour distinguer les méthodes qui vont être appelées par le noyau (les xxxAction()) des autres méthodes que vous pourriez créer au sein de votre contrôleur.

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 Symfony2, 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 faites 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 de faire : {{ 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 Symfony2

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

1. Créons le fichier du template

Le répertoire des templates (ou vues) d'un bundle se trouve dans le dossier Resources/views. Ici encore, on ne va pas utiliser le template situé dans le répertoire Default généré par Symfony2. Créons notre propre répertoire Advert et créons notre template index.html.twig dans ce répertoire. Nous avons donc le fichier src/OC/PlatformBundle/Resources/views/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 :

{# src/OC/PlatformBundle/Resources/views/Advert/index.html.twig #}

<!DOCTYPE html>
<html>
    <head>
        <title>Bienvenue sur ma première page avec OpenClassrooms !</title>
    </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 simple fichier contenant uniquement du code HTML pur !

2. 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 indexAction() que nous allons appeler le template.

Pour accéder aux méthodes de gestion des templates, nous allons faire hériter notre contrôleur du contrôleur de base de Symfony, qui apporte quelques méthodes bien pratiques dont nous nous servirons tout au long de la suite du cours. Notez donc l'héritage dans le code suivant.

Ensuite, la méthode concrête que nous utilisons pour récupérer le contenu d'un template est la méthode $this->get('templating')->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/OC/PlatformBundle/Controller/AdvertController.php

namespace OC\PlatformBundle\Controller;

// N'oubliez pas ce use :
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

class AdvertController extends Controller
{
  public function indexAction()
  {
    $content = $this->get('templating')->render('OCPlatformBundle:Advert:index.html.twig');
    return new Response($content);
  }
}

Nous avons simplement hérité le contrôleur de base, et rajouté la ligne 15 pour récupérer le contenu du template.

La convention pour le nom du template est la même que pour le nom du contrôleur, souvenez-vous : NomDuBundle:NomDuContrôleur:NomDeLAction. Puis, nous avons adapté la création de l'objet Response pour lui passer notre nouvelle variable $content à la place de notre "Hello World" écrit à la main. 

$this->get('templating')  ? Qu'est-ce que c'est exactement ?

Bonne question ! Cette syntaxe $this->get('mon_service') depuis les contrôleurs retourne un objet dont le nom est "mon_service" , cet objet permet ensuite d'effectuer quelques actions. Par exemple ici l'objet "templating" permet de récupérer le contenu d'un template grâce à sa méthode render .

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/Symfony/web/app_dev.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, "nom") et leur valeur (ici, "winzou") :

<?php
$content = $this
    ->get('templating')
    ->render('OCPlatformBundle:Advert:index.html.twig', array(
        'nom' => 'winzou'
    )
);

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

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

C'est tout ! Rechargez la page. Bonjour à vous également. :) 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à anoncé, 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 lire, écrire, éditer 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.

Un peu de nettoyage

Avec tous les éléments générés par Symfony2 et les nôtres, il y a un peu de redondance. Vous pouvez donc supprimer joyeusement :

  • Le contrôleur Controller/DefaultController.php ;

  • Le répertoire de vues Resources/views/Default ;

  • La route oc_platform_homepage dans Resources/config/routing.yml.

Ainsi que tout ce qui concerne le bundle AppBundle,  un bundle de démonstration intégré dans la distribution standard de Symfony2 et dont nous ne nous servirons pas. Supprimez donc :

  • Le répertoire src/AppBundle  ;

  • La lignes 19 du fichier app/AppKernel.php, celle qui active le bundle : new AppBundle\AppBundle() ; 

  • Les lignes 5 à 7 du fichier app/config/routing.yml, celles qui importent le fichier de route du bundle AppBundle (app: resource: "@AppBundle/Controller/" type: annotation" ).

Schéma de développement sous Symfony2

Si vous rafraîchissez la page pour vérifier que tout est bon, il est possible que vous ayez une erreur ! En effet, il faut prendre dès maintenant un réflexe Symfony2 : vider le cache. Car Symfony, pour nous offrir autant de fonctionnalités et être si rapide, utilise beaucoup son cache.

Le cache est constitué de fichiers PHP prêt à ê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 (un array), ce qui sera bien plus rapide à charger la prochaine fois.

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, Symfony2 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 app/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 étrange. Dans ce cas, un petit php app/console cache:clear résout le problème en trois secondes !

Typiquement, un schéma classique de développement est le suivant :

  • Je fais des changements, je teste ;

  • Je fais des changements, je teste ;

  • Je fais des changements, je teste : ça ne marche pas, je vide le cache : ça marche ;

  • Je fais des changements, je teste ;

  • Je fais des changements, je teste ;

  • Je fais des changements, je teste : ça ne marche pas, je vide le cache : ça marche ;

  • ...

  • En fin de journée, j'envoie tout sur le serveur de production, je vide obligatoirement le cache pour le mode prod, je teste : ça marche.

Évidemment, quand je dis « je teste : ça ne marche pas », j'entends « ça devrait marcher et l'erreur rencontrée est étrange ». Si vous faites une erreur dans votre propre code, ce n'est pas un cache:clear qui va la résoudre ! :p

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 Symfony2. Vous avez des notions de bundles, 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. :)

Enfin, le code source final du site que nous allons construire ensemble est disponible à l'adresse suivante : www.tutoriel-symfony2.fr/livre/codesource. Il est un peu tôt pour que vous alliez le voir, car il contient le code final alors que nous allons le construire pas à pas grâce à ce cours. Cependant, il peut être d'une bonne aide, allez y jeter un oeil de temps en temps. ;)

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 former une page HTML, un flux RSS, un e-mail, etc.

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