Guillaume Rivière 2019 – 2024

Le logo de la CCI Bayonne Pays Basque

Développer des applications full web : devenir développeur full-stack

TP2 : Serveur avec Symfony et Doctrine

BUTS PÉDAGOGIQUES

  • Création de projets Symfony
  • Utilisation de l'ORM Doctrine
  • Mise en place d'un webservice d'API en JSON

Dans ce sujet de TP nous effleurons la création de pages web avec le framework Symfony{Missing Image}. L'objectif principal des suivants exercices est l'utilisation du framework Symfony{Missing Image} pour construire une application permettant d'interroger une base de données MySQL avec l'ORM Doctrine{Missing Image}, afin de mettre en œuvre un webservice d'API délivrant ces données au format JSON{Missing Image}.

Exercice 1 • Créer et tester un projet Symfony

Créons un projet Symfony{Missing Image} qui s'appellera « HelloSymfony » :

  1. Ouvrez un terminal {Missing Image} sur le bureau № 3, puis créez le nouveau projet HelloSymfony dans le répertoire /home/estia/devel/ :
    • cd ~/devel
    • composer create-project symfony/skeleton hello-symfony
    Vérifiez le contenu du répertoire de projet fraîchement créé :
    • cd hello-symfony
    • ls
  2. Ajoutez les composants suivants dans le projet :
    • composer require doctrine/annotations
    • composer require twig/twig
    • composer require twig/extra-bundle
    • composer require symfony/web-server-bundle --dev ^4.4.2

Maintenant, observons l'exécution par défaut de ce nouveau projet Symfony{Missing Image} qui est encore intact :

  1. Ouvrez un terminal {Missing Image} sur le bureau № 7, puis démarrez cette application PHP avec l'appel suivant :
    • cd devel/hello-symfony/
    • php bin/console server:run
  2. Allez sur le bureau № 2, et avec le navigateur web (Chromium{Missing Image} ou Firefox{Missing Image}), accédez à l'URL suivante :
    • http://127.0.0.1:8000
    {Missing Image}

Observez le code source de la page web :

⇝ Trouvez-vous des traces de Javascript dans le code source de la page ? (c.-à-d., des balises <script/> ou des extentions .js)

Exercice 2 • Modifier un template Twig

Même si ce n'est pas l'objectif principal de ce TP, prenons quelques minutes pour observer le système de templating Twig qui est utilisé par Symfony.

  1. Depuis le terminal {Missing Image} sur le bureau № 3, dans le répertoire /home/estia/devel/hello-symfony/, installez le bundle « Maker » :
    • composer require symfony/maker-bundle --dev -W
  2. À l'aide du « Maker », que nous venons d'installer, générez un nouveau contrôleur appelé Default :
    • php bin/console make:controller Default
  3. Allez sur le bureau № 2, et avec le navigateur web, accédez à l'URL suivante :
    • http://127.0.0.1:8000/default
    {Missing Image}
  4. Les quatre fichiers qui nous intéressent sont les suivants :
    /home/estia/devel/
                     |-hello-symfony/
                                    |-config/
                                    |       |-routes.yaml
                                    |-src/
                                    |    |-Controller/
                                    |    |           |-DefaultController.php
                                    |-templates/
                                         |-base.html.twig
                                         |-default/
                                                  |-index.html.twig
    1. Le fichier routes.yaml décrit des règles de routage.
    2. Le fichier DefaultController.php est le contrôleur (une classe PHP) que nous venons de créer.
    3. Le fichier base.html.twig définit un modèle de base utilisable par d'autres fichiers Twig.
    4. Le fichier index.html.twig est le template Twig qui vient d'être créé pour le nouveau contrôleur Default que nous venons de créer. Il utilise le fichier base.html.twig comme modèle.
  5. Ouvrez ces quatre fichiers dans un éditeur de texte ou dans un IDE. Par exemple, depuis le terminal :
    • gedit config/routes.yaml src/Controller/DefaultController.php templates/base.html.twig templates/default/index.html.twig&
  6. Observez le code de la méthode index() de la classe DefaultController dans le fichier DefaultController.php :
    • Dans le commentaire qui précède la déclaration de cette méthode, nous voyons une annotation « @Route » qui associe cette méthode au routage /default.
    • Cette méthode retourne le résultat de la méthode render() qui traite le fichier de template Twig associé au contrôleur, tout en transmettant le paramètre controller_name en lui donnant une valeur.
    • Modifions le nom de ce paramètre ainsi que la valeur :
      • Remplacez controller_name par msg
      • Remplacez DefaultController par Description de mon site web.
    • Enregistrez le fichier
  7. Dans le fichier index.html.twig :
    • Remplacez le contenu du bloc title par Accueil
    • Dans le bloc body, effacez le contenu de la balise <div/> et remplacer par un titre de niveau 1 affichant « Accueil » et un paragraphe qui affiche la variable Symfony msg :
          <h1>Accueil</h1>
       
          <p>{{ msg }}</p>
    • Enregistrez le fichier
  8. Allez sur le bureau № 2, et avec le navigateur web, et vérifiez le nouvel affichage de la page :
    • http://127.0.0.1:8000/default
    {Missing Image}
  9. Nous allons maintenant définir notre contrôleur comme celui à utiliser à la racine « / » du serveur. Pour ce faire, dans le fichier routes.yaml, retirez les croisillons « # » en début des trois lignes :
    index:
        path: /
        controller: App\Controller\DefaultController::index
  10. Allez sur le bureau № 2, et avec le navigateur web, et vérifiez la page qui s'affiche avec cette URL :
    • http://127.0.0.1:8000
    {Missing Image}

Exercice 3 • Webservice d'API en JSON

Note : Pour la suite, les explications détaillées ne sont pas encore disponibles : seulement les grandes lignes sont données pour vous guider.
⇝ Appuyez-vous sur la documentation (abondante) et les exemples (foisonnants) à partir d'Internet : savoir se former continuellement (au fil de l'évolution des technologies) est une qualité cruciale des informaticiens.

Créer un nouveau contrôleur d'API (c.-à-d., sans template Twig) : ce contrôleur répondra en envoyant des données JSON. Voici pour le créer :

Testez le résultat dans un navigateur web :

Dans Firefox, cliquez sur l'onglet « Raw Data » ou « Données brutes » pour voir le fichier brut.

Une autre façon pratique de tester le service est de le faire avec CURL depuis le terminal :

Modifiez pour que ce contrôleur retourne une liste d'oiseaux, de manière identique à celle de l'exercice 7 du TP1. Ajoutez à cette liste quelques oiseaux nicheurs du Poitou.

Ajoutez le composant NelmioCorsBundle dans le projet Symfony :

Modifiez la valeur de la variable CORS_ALLOW_ORIGIN dans le fichier .env du projet :

Redémarrez le serveur de symfony

Côté front-end : en utilisant la bibliothèque axios, chargez maintenant la liste d'oiseaux (dans la page 4) partir d'un JSON obtenu en interrogeant le webservice d'API (dans le hook created, plutôt que mounted).

Côté back-end : ajoutez maintenant, en plus du champ « nom », deux autres champs « id » et « nbr » dans le JSON. Donnez des valeurs incrémentales pour le champ id et des valeurs quelconques pour le champ « nbr ».

Côté front-end : essayez d'initialiser le props start des compteurs à partir du champ « nbr » reçu dans le JSON.

Exercice 4 • Interrogation de MySQL avec l'ORM Doctrine

Nous voulons maintenant une base de données MySQL avec une table qui contiendra la liste de nos oiseaux nicheurs du Poitou.

Ajoutez l'ORM Doctrine dans le projet avec :

Créez la BDD db_poitou_birds :

Ouvrez le fichier caché .env qui se trouve dans le répertoire du projet et remplacer la ligne de la variable DATABASE_URL par la ligne suivante dans le bloc « doctrine/doctrine-bundle » qui est en fin de fichier :

Créez une nouvelle entité Bird (id:integer, nom:string, nbr:integer) en répondant aux questions de l'utilitaire du Maker :

Ouvrez le fichier src/Entity/Bird.php et vérifiez que cela correspond bien.

Faîte la migration vers la BDD pour que la table soit créée en accord avec le schéma décrit par l'entité :

Insérez des noms d'oiseaux dans la table (par exemple, via phpMyAdmin à l'adresse http://127.0.0.1/phpmyadmin avec l'utilisateur root et le mot de passe estia).

Modifiez le contrôleur Bird pour construire la réponse à partir de la BDD, en vous aidant des Repositories de l'ORM Doctrine :

Vérifiez en testant avec CURL depuis le terminal :

Exercice 5 • Webservice d'API avec le bundle API Platform

Nous avons maintenant compris le mécanisme, alors recommençons avec un gestionnaire d'API pour accélérer le développement de l'application :

  1. Commencez par supprimer les tables précédemment créés :
    • mysql -uroot -p
      • USE db_poitou_birds;
      • SHOW TABLES;
      • DROP TABLE doctrine_migration_versions;
      • DROP TABLE bird;
      • quit
  2. Supprimez l'entité « Bird » :
    • rm src/Entity/Bird.php
    • rm src/Repository/BirdRepository.php
    • rm migrations/*
  3. Videz le cache :
    • php bin/console cache:clear
  4. Ajouter API Platform dans le projet :
    • composer require api-platform/core:2.6
    • composer require doctrine/doctrine-migrations-bundle

Créons maintenant de nouveau des entités :

  1. Créez de nouveau l'entité Bird (id:integer, nom:string, nbr:integer) en utlisant :
    • php bin/console make:entity
    ⇝ vous répondrez yes à la nouvelle question « Mark this class as an API Platform resource »
  2. Faîtes la migration pour que la table soit créée dans la BDD :
    • php bin/console make:migration
    • php bin/console doctrine:migrations:migrate
  3. Pour mieux décrire les espèces d'oiseaux (nicheur, hivernant, migrateur …), créez une nouvelle entité Categorie (libelle:string) en utilisant aussi :
    • php bin/console make:entity
    ⇝ vous répondrez yes à la nouvelle question « Mark this class as an API Platform resource »
    ⇝ vous ajouterez un deuxième champ appelé « birds » qui sera de type ManyToMany : puis, répondez qu'il sera relié à la classe « Bird », puis répondez yes pour ajouter une propriété à « Bird ».
  4. Faîtes la migration pour que les tables soient créées dans la BDD :
    • php bin/console make:migration
    • php bin/console doctrine:migrations:migrate
  5. Remarquez qu'une table intermédiaire a été créée pour la relation N-N (c.-à-d. ManyToMany) :
    {Missing Image}

Allez sur le bureau № 2, et avec le navigateur web, accédez à le centre de gestion de votre API :

Exercice 6 • Interroger le nouveau webservice d'API

Pour tester les possibilités CRUD de ce nouveau webservice RESTfull, envoyons des requêtes avec CURL en utilisant quatre des méthodes HTTP (POST, GET, PUT, DELETE) reconnues par ce webservice :

  1. [CREATE] Insérez un nouvel oiseau :
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{"nom":"Héron Cendré", "nbr":10}'
    ⇝ Connectez-vous par exemple sur http://127.0.0.1/phpmyadmin pour vérifier le contenu de la table bird
    ⇝ Vous pouvez aussi tout simplement faire ceci depuis un terminal (c'est utile, car une fois déployé sur le Cloud, cela est parfois l'unique moyen d'accès depuis votre VM) :
    • mysql -uroot -p
      • USE db_poitou_birds;
      • SELECT * FROM bird;
  2. [CREATE] Insérez plein de nouveaux oiseaux :
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Roitelet huppé", "nbr": 0 }'
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Bruant des roseaux", "nbr": 0 }'
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Butor étoilé", "nbr": 0 }'
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Héron pourpré", "nbr": 0 }'
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Mésange noire", "nbr": 0 }'
    • curl -X POST "http://127.0.0.1:8000/api/birds" -H "Content-Type: application/ld+json" -d '{ "nom": "Moineau friquet", "nbr": 0 }'
  3. [READ] Récupérez les informations de tous les oiseaux :
    • curl -X GET "http://127.0.0.1:8000/api/birds"
    Pas très digeste à lire, n'est-ce pas ? Testez ceci :
    • curl -X GET "http://127.0.0.1:8000/api/birds" | json_pp
  4. [READ] Récupérer les informations de l'oiseau avec l'id de valeur 1 :
    • curl -X GET "http://127.0.0.1:8000/api/birds/1"
    De même, vérifiez avec un peu plus de lisibilité :
    • curl -X GET "http://127.0.0.1:8000/api/birds/1" | json_pp
  5. [UPDATE] Modifiez la valeur du compteur de l'oiseau avec l'id de valeur 1 :
    • curl -X PUT "http://127.0.0.1:8000/api/birds/1" -H "Content-Type: application/ld+json" -d '{ "nbr" : 11 }' | json_pp
  6. [DELETE] Supprimez l'oiseau avec l'id de valeur 1 :
    • curl -X DELETE "http://127.0.0.1:8000/api/birds/1"