Développeur

Sommaire

Débuter avec Symfony 3 : Créer sa première page web
|

Symfony est actuellement l'un des frameworks php les plus utilisés au monde avec plus de 500 millions de téléchargements. Il est très complet avec une grande communauté qui fournit des composants afin d'étendre ses possibilités. Dans ce tutoriel nous allons nous initier à Symfony 3.

Pré-requis

Dans ce tutoriel, nous considérons que les logiciels MySQL et Apache ont été déjà installés. Sinon c'est le moment de le faire. Je vous recommande de télécharger et d'installer le package XAMPP pour aller rapidement.

Et bien entendu vous possédez également un navigateur tel que Mozilla Firefox ou Google Chrome. Personnellement je préfère Mozilla Firefox pour des raisons que ne perderai du temps à vous expliquer dans ce tutoriel.

Par ailleurs, je vous recommande d'utiliser MySQL Workbench si vous êtes sous Linux et MySQL Front si vous utilisez un Windows pour la gestion de vos bases de données. Je les trouve plus pratique, simple et rapide que PHPMyAdmin. Cependant, il n'est pas rare de voir MySQL Front planté ou demander des mise à jour de manière anarchique pour les utilisateurs Windows.

Si vous avez voulu développer un site avec Symfony, cela suppose que vous avez quelques bonnes notions en programmation orienté objet avec PHP et que vous connaissez un peu le modèle MVC.

Installation

Dans ce tutoriel, nous allons travailler avec la dernière version de Symfony : 3.1. Le framework a franchi la barre des 500 millions de téléchargements, ce qui donne un aperçu du nombre de développeurs qui l'utilisent pour concevoir des sites web.

Pour commencer, nous allons télécharger l'installeur de Symfony 3.1 :

Sous Linux, dans le terminal :

on va faire une requête curl pour obtenir l'installeur dans le répertoire /usr/local/bin :

$ sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony

Ensuite nous allons rendre l'installeur exécutable :

$ sudo chmod a+x /usr/local/bin/symfony

Sous Windows, dans la console :

On se place d'abord dans le répertoire qui contient nos projets web (chez moi: C:\wamp\www)

cd C:\wamp\www

Ensuite via php, on télécharge l'installeur :

c:\> php -r "file_put_contents('symfony', file_get_contents('https://symfony.com/installer'));"

Ensuite dans votre terminal ou votre console, il faut vous placer dans le répertoire de vos projets web, celui que l'adresse http://localhost/ pointe après l'installation de Apache (Wamp ou Lamp), puis exécutez la commande qui suit :

$ symfony new omega 3.4

Omega est le nom que nous avons donné à notre projet de développement web, mais vous pouvez le changer en tout autre nom.

Et voilà, après quelques secondes d'installation, vous devriez avoir un dossier nommé omega dans votre répertoire web avec des dossiers et fichiers par défaut.

Pour vérifier que tout s'est bien passé, placez-vous dans le nouveau dossier Omega puis exécutez la commande :

$ php bin/console server:run

Ensuite entrez l'url qui suit dans votre navigateur : http://localhost:8000

Et vous devriez avoir une petite jolie et simple page de symfony qui s'affiche.

La précédente commande a fait en sorte que le serveur apache sur notre machine (local) écoute des requêtes http (pointant vers le projet omega) sur le port 8000.

Organisation des dossiers de Symfony

Après la création de notre premier projet, nous devrons avoir les dossiers suivants :

  • « app » qui contient tous les fichiers de configuration, de journalisation et de cache et contiendra également nos vues (le front-end).
  • « src » contiendra tous les fichiers sources (code) qui vont exécuter les requêtes et effectuer les traitement de données (niveau back-end).
  • « web » est la passerelle vers le contenu de notre site, toutes les requêtes transitent par lui via le fichier « app.php » en mode production et « app_dev.php » en mode développement ou test.
  • « vendor » est le répertoire dans lequel tous les fichiers sources des composants nécessaires pour le bon fonctionnement du site s'installent. S'il vous manque un composant, que vous le télécharger et l'installer, logiquement, les fichiers sources devraient se retrouver dans « vendor ».
  • « bin » qui contient des fichiers systèmes nécessaire au fonctionnement de Symfony. Ce répertoire qui nous permettra d'exécuter des commandes symfony que nous verrons plus tard.

Créer un bundle avec Symfony

Nous avions nommé le projet Omega qui va ensuite contenir des sous-projets ou des modules. Un sous-projet ou un module avec Symfony est appelé bundle. Nous allons donc dorénavant utiliser le mot bundle comme expression afin que nous soyons familier avec le langage Symfony. Un bundle peut-être le module de gestion du blog de l'entreprise qui peut être séparé du reste du site et surtout, qui peut fonctionner de manière indépendante.

Nous allons donc créer le bundle du blog.

Méthode 1 : Utiliser le générateur de bundles

Générer le bundle

Faites ctrl + c pour quitter le mode écoute.

Ensuite :

$ php bin/console generate:bundle

Si tout va bien, vous obtenez un message colorié en bleu :

Welcome to the Symfony2 bundle generator

Espace de nom du bundle

Ensuite, la console vous demande si vous envisagez utiliser le bundle dans d'autres applications/projets. Un bundle peut-être utilisé dans un ou plusieurs projets différents. Je disais au début qu'on peut faire en sorte que les bundles fonctionnent de manière indépendante. On peut créer un bundle pour l'inscription et la connexion des utilisateurs, et l'utiliser pour tous nos prochains projets. Si c'est le cas, il faut saisir « yes ». Sinon, si le bundle n'a d'utilité que dans le projet courant, il faut saisir « no », la valeur par défaut.

Tous les bundles d'un projet Symfony doivent terminer par le suffixe Bundle.

Nous allons saisir « no » pour avancer.

Si nous décidons de saisir « yes », la console nous demandera de saisir l'espace de nom du bundle pour éviter les conflits (nommage), permettre à Symfony de référer le bundle par rapport à un projet et permettre la portabilité.

Pour définir l'espace de nom, on écrit le nom du projet suivi du nom du bundle les deux séparés par un slash. Faites très attention à utiliser le slash « / » pour séparer le nom du projet du nom du bundle et non pas un anti-slash « \ ».

Mais comme nous avons décidé de saisir « no », nous n'avons pas besoin d'un espace de nom, nous passons directement à la prochaine étape.

Sinon, alors il faut saisir :

Omega/BlogBundle
/*Le bundle blog est contenu dans le projet Omega*/

Nom complet du bundle

La console nous demande maintenant de saisir le nom complet du bundle et nous propose un nom par défaut : « BlogBundle » pour le cas de « no » pour l'étape précédente et « OmegaBlogBundle » pour le cas de « yes ». Ce dernier nom est simplement une composition du nom du projet et du nom du bundle. Vous pouvez toute fois le changer en enlevant le nom du projet et conserver juste BlogBundle comme le cas de « no ». Mais je vous recommande de garder le nom par défaut.

Appuyer donc sur la touche « Entrée » pour accepter et valider le nom proposé par défaut et continuons.

Dossier de stockage des fichiers sources

La console vous demande maintenant le chemin de destination pour créer le dossier du projet et du bundle. Avec Symfony, tout ce qui est code source du backend est enregistré dans le répertoire « src » contenu dans le dossier du projet. C'est ce dossier que la console vous suggère par défaut entre crochet, validez cette proposition pour continuer.

Maintenant, le terminal nous demande quel format nous souhaitons utiliser pour les fichiers de configuration de notre bundle. Nous avons 4 options : yml, php, xml ou les annotations. Je propose que nous avancions avec le format annotations par défaut. Mais pour plus de flexibilité et de bonne structuration du code, à un moment, il faudra privilégié le format yml qui plus est facile est comprendre.

Validons donc le format annotations proposé par défaut.

Avec Symfony 2, le terminal demandera encore si nous souhaitons générer le répertoire de code snippets. Il faut valider « yes » à tous les coups.

Notre premier bundle est maintenant créé. Un dossier nommé « BlogBundle » qui contiendra tout ce qui a rapport avec le blog du projet Omega a été créé dans le répertoire src de notre projet.

Vérifions que tout marche jusqu'à là

Exécutons à nouveau la commande qui suit :

$ php bin/console server:run

Et rechargeons notre page : http://localhost:8000

Nous devrions maintenant obtenir un « hello word ».

Si c'est le cas, alors tout va bien, sinon posez votre problème en commentaire.

Deuxième méthode : le faire manuellement

  • Allez dans le dossier « Omega/src ».
  • Créer un dossier nommé « TestBundle » et ouvrez-le.
  • Créer le fichier « TestBundle » et insérez le code qui suit :
    ?php
    namespace TestBundle;
    use Symfony\Component\HttpKernel\Bundle\Bundle;
    class TestBundle extends Bundle
    {
    }
    
  • Créer les dossiers « Controller » et « Resources ».
  • Dans le dossier « Resources », créez les dossier « public », « config » et « views ».
  • Dans le dossier « public », créez les dossiers « js » et « css ».
  • Ouvrez le fichier « AppKernel.php » qui se trouve dans le dossier « omega/app ».
  • Ajouter le code ci-dessous à l'initialisation du tableau bundles dans la fonction registerBundles() :
BlogBundle\BlogBundle(),

Cet ajout permet à Symfony de savoir qu'un nouveau bundle a été créé.

Créez un fichier « routing.yml » dans le répertoire « config » de « Resources ».

Insérez le code ci-dessous dans le fichier « routing.yml »

delta_blog_homepage:
    path:     /hello/{name}
    defaults: { _controller: TestBundle:Default:index }

Ce petit code est une route, le lien que nous allons copier dans notre navigateur pour accéder à la page. Nous allons avoir plus d'explications plus loin.

Insérez le code qui suit dans le fichier « routing.yml » du répertoire « Symfony/app/config »

delta_blog:

resource: "@TestBundle/Resources/config/routing.yml"

prefix: /test/

Ce code est pour dire à Symfony de lire toutes les routes contenu dans le fichier « routing.yml » de DeltaBlogBundle de la propriété resource puis de préfixer tous les liens de cette ressource là par /test/. Ce qui veut dire tous liens de TestBundle seront préfixés par /test/.

Voilà en ce qui concerne la méthode manuelle. Suivez le reste des étapes pour finaliser la création d'une page web.

Symfony et le modèle MVC

Pour respecter les bonnes pratiques du développement web avec une bonne structuration du code, il est fréquent et recommandé d'utiliser le modèle Modèle – Vue – Contrôleur. Cela dit, tout ce qui concerne les bases de données c'est-à-dire les classes représentant une table doivent être regroupées dans un dossier, tout ce qui a rapport au front-end c'est-à-dire les vues, les fichiers JavaScript et CSS sont regroupés dans un dossier et enfin, tout ce qui concerne les opérations traitement de données (insertion, mise à jour, consultation) est stocké dans un autre dossier.

Symfony gère très bien le modèle MVC. Remarquez que dans le dossier de notre bundle : « Symfony/src/Omega/BlogBundle », il y a un dossier « Controller » pour contenir tous les fichiers contrôleurs du bundle. Il y a également un dossier « Resources » qui va contenir l'ensemble des fichiers intervenants dans le front-end et qui concourent à l'expérience utilisateur. Dans ce répertoire, vous avez un dossier « views » qui va contenir les vues et un dossier « config » pour les services et les routes (format yml).

Une route représente un lien à saisir dans le navigateur pour accéder à une page web.

Nous pouvons y (dans le dossier « config ») créer un dossier « public » pour les feuilles de style et les fichiers JavaScript, un dossier « translations » pour le multilingue.

Enfin, par défaut, Symfony ne crée pas un dossier pour les classes représentants les tables d'une base de données. D'ailleurs, tous les sites n'ont pas besoin d'une base de données pour fonctionner. Mais étant donné qu'un blog a besoin d'une base de données pour enregistrer les différents utilisateurs, articles et commentaires, il nous faut un dossier pour respecter le modèle MVC. Nous allons y revenir.

Créer une première page

Nous avons pu obtenir « Hello omega » car par défaut Symfony a créé un contrôleur contenant une fonction, une vue et une route pour nous. Nous allons maintenant créer notre propre route (lien), notre premier contrôleur et la vue qu'il affichera.

Créer une vue avec Symfony

Pour les vues avec Symfony, nous allons utiliser le moteur de template « twig ». Il a été créé par Sensiolabs, la société éditrice de Symfony. Twig a été développé pour faciliter la gestion des vues et offre plusieurs possibilités telles que les inclusions, les boucles, les conditions, etc. Cela dit, si vous le désirez, vous pouvez vous en passer et utiliser du pur PHP comme à l’accoutumé.

Les vues sont enregistrées dans le répertoire « Resources/views » du bundle. Étant donné que les vues sont généralement liés à un cas d'utilisation ou objet (classe, table), il est plus propre de créer un dossier pour les vues de chaque cas d'utilisation ou objet. Ainsi, si nous avons des vues concernant l'enregistrement, la modification d'un utilisateur, nous allons créer un dossier « Users » dans « Resources/views » pour les regrouper. Un autre dossier sera créé pour regrouper les vues concernant l'ajout et la modification d'un article.

Un fichier twig avec Symfony a pour extension : .html.twig.

Il existe un répertoire « Default » par défaut. Nous allons créer nos premières vues à l'intérieur de ce répertoire.

Créons donc une vue nommée « index.html.twig » dans « Resources/views/Default ». Sinon que ce fichier existe déjà normalement. Supprimez son contenu et insérer la petite portion de code qui suit :

<h1>>itre de ma première page Symfony</h1>

<p>Ceci est un paragraphe de textes qui illustre le fonctionnement d'une vue avec Symfony et Twig. Pour le moment, il ne s'agit que d'une simple page html</p>

Nous allons ensuite demander au contrôleur d'afficher cette petite page que nous venons de créer.

Créer un contrôleur avec Symfony

De la même manière qu'il faut créer un dossier pour chaque cas d'utilisation ou objet au niveau des vues, il est également recommandé de créer un contrôleur pour chaque cas d'utilisation ou objet. Un contrôleur avec Symfony est un fichier .php. Son nom doit commencer par une lettre majuscule et doit être suffixé par le mot Controller. Ainsi, pour la gestion des utilisateurs par exemple, nous aurons un contrôleur nommé « UserController.php » et « ArticleController.php » pour la gestion des billets de blog.

Et comme les développeurs de Symfony sont gentils, ils ont également prévu un contrôleur par défaut nommé « DefaultController.php ». Nous allons donc l'utiliser pour commencer.

Comme tout framework web, Symfony impose également ses règles. Un fichier contrôleur contient au moins une classe possédant le même nom que le fichier et qui hérite de la classe Controller qui se trouve dans l'espace de nom Symfony\Bundle\FrameworkBundle\Controller\Controller. Dans notre cas, « DefaultController.php » contiendra donc une classe nommée DefaultController.

Un contrôleur contient des actions mais peut aussi contenir de simples méthodes. Une action en Symfony n'est rien d'autre qu'une méthode que le contrôleur peut exécuter à la demande d'un utilisateur (requête http) afin de lui sortir une réponse. Une action est toujours suffixée du mot « Action ». Dans notre contrôleur DefaultController, nous allons donc ajouter une action indexAction. En fait, cette action existe déjà par défaut.

Avec Symfony, pour importer un fichier, on utilise le mot clé use. Ainsi, pour importe le fichier qui contient la classe Controller que tous les contrôleurs doivent héritées, nous allons ajouter ce qui suit à l'entête de notre fichier DefaultController.php :

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

Pour finir, une action dans un contrôleur doit toujours retourner une réponse, ce qui est assez logique. Lorsque le client web émet une requête http via le navigateur, il est impératif qu'on lui renvoie une réponse. Par exemple, il demande de voir les informations d'un utilisateur en soumettant un formulaire, le contrôleur exécute l'action propice pour cette requête et renvoie une réponse au client, cela peut être une réponse html, xml, json ou autres.

Il y a plusieurs manières pour envoyer une réponse à la suite d'une requête.

Une réponse brute

Il faut inclure l'entête adéquate, la classe Response :

use Symfony\Component\HttpFoundation\Response ;

Ensuite il faut retourner un objet response :

return new Response("La réponse ici, cela peut être du html, du txt, du xml ou du json");

Une vue

Symfony a prévu une méthode render à tous les contrôleurs qui leur permet de renvoyer une vue sous forme de réponse. Notre action devra donc contenir le code qui suit :

return $this→render("BlogBundle:Default:index.html.twig");

Le paramètre de la méthode render est la vue que le contrôleur doit afficher après traitement.

  • BlogBundle : c'est le nom du bundle qui contient la vue que l'on veut affichier

  • Default : est le sous-dossier que nous avons créé dans le répertoire « Resources/views » pour regrouper les vues d'un même cas d'utilisateur ou d'un même objet.

  • Index.html.twig : est le nom du fichier qui contient le code html à afficher, la vue proprement dite.

Si par exemple vous n'aviez pas créé un dossier pour regrouper les vues comme je l'ai recommandé et que vous avez créé vos vues directement dans le répertoire « views », le paramètre de render sera comme ceci :

return $this→render("BlogBundle::index.html.twig");

Nous n'avons plus mis Default entre le nom du bundle et celle la vue.

Faites attention aux « : ».

Une route avec Symfony : les annotations

Nous allons maintenant spécifier une la route par laquelle un utilisateur peut appeler l'action index du contrôleur.

Souvenez-vous, on avait choisi le format annotation pour nos routes lors de la génération du bundle, c'est donc ce format là que nous allons maintenant utiliser.

Il faut d'abord inclure la bonne entête :

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

Ensuite, il faut ajouter ce morceau de code juste avant l'action concernée :

/**
 * @Route("/")
 */

Voilà la syntaxe basique de la déclaration d'une route avec des annotations.

"/" pour dire qu'il faut exécuter l'action qui vient juste après cette annotation lorsque le client veut afficher l'index du site.

Vous pouvez changer "/" par quelque chose comme "/home/". Ainsi, pour exécuter l'action, il faudrait saisir http://localhost:8000/home/ dans le navigateur au lieu de http://localhost:8000/.

Récapitulons

Pour récapituler, le squelette d'un contrôleur Symfony avec une action et une route ressemble à ceci :

Action qui envoie une vue html

<?php
// L'espace de nom du contrôleur
namespace Omega\BlogBundle\Controller;
// Inclusion des entêtes nécessaires
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
// Début de notre classe contrôleur Default
class DefaultController extends Controller
{
    // Définition de la route
    /**
     * @Route("/")
     */
    // Définition de notre méthode action index
    public function indexAction()
    {
        /* Des lignes d'instructions ici */
        // Nous envoyons notre vue comme réponse à la requête du client
        return $this->>render('BlogBundle:Default:index.html.twig');
    }
}

Action qui envoie une réponse brute

<?php
// L'espace de nom du contrôleur
namespace Omega\BlogBundle\Controller;
// Inclusion des entêtes nécessaires
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
// N'oubliez pas d'inclure l'entête de la classe Response
use Symfony\Component\HttpFoundation\Response;
// Début de notre classe contrôleur Default
class DefaultController extends Controller
{
    // Définition de la route
    /**
     * @Route("/")
     */
    // Définition de notre méthode action index
    public function indexAction()
    {
        /* Des lignes d'instructions ici */
        // Nous envoyons notre message comme réponse à la requête du client
        return new Response("Envoie d'une réponse brute depuis une action");
    }
}

Ce type d'envoie est très pratique pour l'envoie de réponses au format JSON, par exemple pour répondre à une requête Ajax.

Testons pour voir si ça marche

Rechargeons la page dans navigateur : http://localhost:8000/

Nous devrions avoir le contenu de notre vue s'affiché.

Sinon, alors il y a sûrement un raté au niveau dees étapes à suivre. Vous pouvez poser votre problème en commentaire.

Passage de paramètres dans les routes

Maintenant nous voulons pouvoir passer des paramètres à nos url et les afficher dans nos vues. Par exemple, l'utilisateur peut saisir http://localhost:8000/son-nom/ et la page lui affiche son nom dans le navigateur.

Pour ce faire, nous allons d'abord modifier légèrement notre route par ce qui suit :

/**
 * @Route("/{username}/")
 */

Nous avons juste rajouter {username} au lien. Les accolades disent à Symfony qu'il s'agit d'une variable. Cela équivaut en quelques sortes à http://localhost:8000/?username="nom_de_utilisateur". Mais cela n'est pas esthétique, c'est plus chargé et pas bon pour la SEO.

Symfony nous facile la tâche avec ce format http://localhost:8000/{username}/, qui ne contient plus le « ? » pour indiquer les paramètres et plus besoins de mettre le nom de la variable, on met uniquement la valeur de la variable dans le lien.

Ensuite, nous allons dire à notre action de recevoir le paramètre qui sera envoyé dans la route. Pour le faire, c'est simple, on ajoute un paramètre du même nom à notre action et Symfony se charge du reste. Notre fonction de vient donc :

public function indexAction($username){
    return $this->render('BlogBundle:Default:index.html.twig');
}

Ensuite, nous allons envoyer ce paramètre à notre vue pour l'afficher.

La méthode render du contrôleur accepte un deuxième paramètre qui est un tableau de type clé-valeur dans lequel nous pouvons mettre tous les paramètres que nous voulons transmettre à la vue.

Ainsi, pour envoyer notre username à la vue (twig), nous devrions avoir ceci :

return $this->render('BlogBundle:Default:index.html.twig',array('username'=>$username));

on a ajouté un tableau comme deuxième paramètre de la méthode render. Ensuite une cellule ayant pour valeur $username (paramètre transmis à l'action via la route) associée à la clé username. Ce dernier aurait pu être nommé autrement.

Maintenant, notre vue reçoit le paramètre, nous pouvons l'afficher en twig. Ajoutons donc le petit code qui suit, juste après la balise <h1> de notre vue :

<strong>Bonjour {{username}},</strong>

Rien de compliqué, nous avons juste demandé à twig de nous afficher le contenu de la variable username qui lui a été transmise en l'entourant de double-accolades.

Maintenant, ajoutons un la valeur « toto » à notre url dans le navigateur comme suit : http://localhost:8000/toto/

Et voilà, le navigateur devrait afficher « Bonjour toto, » et ce sera tout pour cette première partie.

Dans une prochaine partie, nous allons découvrir comment lier Symfony à une base de données, faire des mise à jour et des requêtes.

Bonus : Créer une route au format yml

Si vous désirez regrouper toutes vos routes dans des fichiers, le format Les fichiers de routes se trouvent dans le dossier « Resources/config » du bundle pour lequel l'on veut créer la route. Par défaut, il contient un fichier nommé « routing.yml ». Pour éviter de créer un autre, nous allons définir nos routes dans ce fichier là.

Lorsque vous ouvrez le fichier « routing.yml », vous remarquerez qu'il contient le code suivant :

blog_homepage:
    path:     /hello/{name}
    defaults: { _controller: BlogBundle:Default:hello }
  • path : pour définir le lien ;
  • defaults : pour définir le contrôleur à appeler et la fonction à exécuter ;
  • _controller : pour dire qu'on veut appeler un contrôleurs ;
  • BlogBundle est le nom complet du bundle, celui qu'on a définit quand on générait le bundle ;
  • Default : le nom du contrôleur à appeler, on met le nom sans le suffixe Controller.
  • hello: c'est le nom de méthode action à exécuter dans le contrôleur. Dans le contrôleur, toutes les actions sont suffixées par « Action » mais ici, on n'ajoute pas le suffixe, Symfony sait qu'il s'agit d'une action. Par contre, si cette action n'existe pas dans le contrôleur, Symfony générera une exception.
  • {name} : name entouré des accolades pour dire qu'il s'agit du variable dans le lien.

Commentez cet article