- Accueil
- Programmation Web S3
- Objectifs de la séance
- Préambule
- Utilisation du moteur PHP local
- Documentation
- Mise en place d'une application
Symfony
- Gestion des versions avec Git
- Création du projet dans
PhpStorm
- Outils de qualité de code (analyse statique de code)
- Documentation du projet
- Mise en place de scripts
Composer
- Désactivation de
Symfony UX Turbo
- Le routeur
- Les vues dans
Symfony
:Twig
- De la route à la vue
- De la vue à la route
- Introduction aux tests fonctionnels
- Configuration de l'accès base de données de l'application
- Consultation des contacts
- Mise en place de votre propre base de données, retour aux bonnes pratiques
Objectifs de la séance ¶
- Créer un projet
Symfony
avec l'outil «symfony
» en ligne de commande (« Symfony CLI ») - Prendre en main
Symfony
dans sa version 5 - Utiliser le routage
- Développer des « templates »
Twig
- Écrire des tests fonctionnels
- Utiliser l'ORM
Doctrine
- Gérer des relations entre entités
- Générer des données factices (« fixtures ») avec «
Foundry
» - Utiliser le composant
Form
- Utiliser le composant
Security
- Mettre en place un « back-office » avec
EasyAdmin
Préambule ¶
L'objectif de ce TP est de vous familiariser avec le développement d'applications Symfony
. Le sujet vous accompagne dans la découverte du framework tout en essayant de se conformer aux bonnes pratiques de Symfony
.
Remarque importante
De nombreux points du sujet consistent en l'observation de fichiers ou de fonctionnements qui s'appuient sur des conventions liées au framework. Ne les négligez pas ! Le but n'est pas de vous faire suivre bêtement un tutoriel mais de vous amener à comprendre ce que vous faites.
Utilisation du moteur PHP local ¶
Vous allez utiliser le moteur PHP installé localement sur le poste de travail. Vous déclencherez le moteur PHP local, directement ou indirectement de diverses manières :
- à l'aide de la commande
php
pour exécuter du codephp -r "code PHP"
- à l'aide de la commande
php
pour exécuter un programmephp -f un_script_PHP
ouphp un_script_PHP
- comme une commande grâce à l'utilisation du shebang en tête d'un programme PHP
bin/console cache:clear
Le programme «
console
» est fourni dansSymfony
, s'utilise comme un script shell, et est écrit en PHP. Sa première ligne est#!/usr/bin/env php
- comme une commande grâce à l'utilisation du shebang en tête d'un paquet PHP (fichier
.phar
)composer.phar update
- en mode server local à travers l'utilisation du serveur Web intégré à PHP
php -S localhost:8000 -t public/
PHP
lance ici un serveur Web local que vous allez interroger avec un navigateur Web.
Documentation ¶
Vous aurez besoin de la documentation de Symfony
ainsi que de celle des diverses API :
Mise en place d'une application Symfony
¶
Vous allez créer des applications Symfony
de façon conventionnelle, en utilisant l'outil « symfony
» en ligne de commande (« Symfony CLI »). Une nouvelle application Symfony
nécessite un peu plus de 80 Mo de sources PHP pour fonctionner (environ 10.000 fichiers dans un peu moins de 2.000 répertoires !). Ces données seront rapidement agrémentées de plusieurs dizaines de mégaoctets de cache générés par Symfony
.
Vous allez installer Symfony
à l'aide de l'outil « symfony
» en ligne de commande (« Symfony CLI ») et pour cela, vous allez devoir l'installer. Cet outil utilise Composer
dont vous devrez vous assurer du bon fonctionnement.
Quelques considérations liées à la configuration système de l'IUT ¶
Remarque importante
Si vous travaillez sur votre ordinateur personnel, sur Linux ou sur Windows, vous pouvez placer le répertoire « symfony-contacts
» du projet où bon vous semble. La partie qui suit concerne uniquement le travail sur les ordinateurs de l'IUT. Cela ne vous empêche pas d'en prendre connaissance.
Votre répertoire d'accueil « $HOME
» se trouve sur un emplacement réseau NFS
, ce qui vous permet de retrouver vos fichiers quel que soit le PC du département sur lequel vous vous connectez. Symfony
utilise le sous-répertoire « var
» du projet pour la gestion de son cache, des traces d'exécution et des données de session. Ces tâches génèrent de nombreuses entrées-sorties sur le système de fichiers, particulièrement inadaptées aux systèmes de fichiers en réseau. Il en va de même pour PhpStorm
qui surveille les modifications de tous les fichiers du projet et ne peut pas fonctionner normalement lorsque ces fichiers sont sur un partage NFS
. Afin d'améliorer les performances de l'application et d'éviter de saturer le serveur de fichiers du département informatique, vous allez travailler dans le répertoire « /working/votre_login
» de la machine sur laquelle vous êtes connecté.
En fin de séance ¶
En fin de séance, vous devez impérativement synchroniser le dépôt distant (en ligne de commande ou avec PhpStorm
)
git commitpuis
git pushfaute de quoi vous perdrez votre travail entre chaque séance !
Pensez également à supprimer votre répertoire de travail /working/votre_login/symfony-contacts
pour éviter la saturation du disque local :
rm -Rf /working/votre_login/symfony-contacts
En début de séance ¶
Lorsque vous reprenez le travail la séance suivante, vous avez trois choix possibles, qui dépendent de la façon dont vous avez travaillé :
- Mettre à jour le dépôt local
cd /working/votre_login/symfony-contacts
git pull
- Effacer le dépôt local et repartir de zéro
cd /working/votre_login
rm -Rf /working/votre_login/symfony-contacts
git clone https://iut-info.univ-reims.fr/gitlab/votre_login/symfony-contacts.git
cd /working/votre_login/symfony-contacts
- Réinitialiser le dépôt local selon le dépôt distant
cd /working/votre_login/symfony-contacts
git fetch
git reset --hard origin/main
Ensuite, dans le répertoire du projet, vous devez et (ré)installer les composants nécessaires à son fonctionnement :
composer install
Vous devrez également reconfigurer l'accès base de données en redéfinissant le fichier « .env.local
»
Installation de l'exécutable « symfony
»
¶
Le développement d'applications Symfony
peut être facilité par l'utilisation de l'outil « symfony
» en ligne de commande (« Symfony CLI »). Ce dernier peut contrôler que le système comporte tous les prérequis pour le développement d'applications Symfony
ou tester la présence de failles de sécurité connues.
Travail à réaliser
- Installez l'exécutable «
symfony
» qui contient le serveur Web local en lançant la commande suivante :wget https://get.symfony.com/cli/installer -O - | bash
--2025-09-08 14:06:03-- https://get.symfony.com/cli/installer Résolution de get.symfony.com (get.symfony.com)… 18.164.52.20, 18.164.52.7, 18.164.52.11, ... Connexion à get.symfony.com (get.symfony.com)|18.164.52.20|:443… connecté. requête HTTP transmise, en attente de la réponse… 200 OK Taille : 6100 (6,0K) [binary/octet-stream] Enregistre : ‘STDOUT’ - 100%[=============================================================>] 5,96K --.-KB/s ds 0s 2025-09-08 14:06:03 (2,49 GB/s) — envoi vers sortie standard [6100/6100] Symfony CLI installer Environment check [*] cURL is installed [*] Tar is installed [*] Git is installed [*] Your architecture (amd64) is supported Download Downloading https://github.com/symfony-cli/symfony-cli/releases/latest/download/symfony-cli_linux_amd64.tar.gz... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 100 6151k 100 6151k 0 0 7388k 0 --:--:-- --:--:-- --:--:-- 41.6M Uncompress binary... Installing the binary into your home directory... The binary was saved to: /home/Users/cutron01/.symfony5/bin/symfony The Symfony CLI was installed successfully! Use it as a local file: /home/Users/cutron01/.symfony5/bin/symfony Or add the following line to your shell configuration file: export PATH="$HOME/.symfony5/bin:$PATH" Or install it globally on your system: mv /home/Users/cutron01/.symfony5/bin/symfony /usr/local/bin/symfony Then start a new shell and run 'symfony'
- Modifiez ou créez le fichier «
.profile
» (à la racine de votre compte) afin qu'il contienneexport PATH="\$HOME/.symfony5/bin:\$PATH"
- Chargez les modifications du «
.profile
»source ~/.profile
InformationLa configuration du shell Bash se fait à l'aide de fichiers de démarrage. Le fichier «
~/.profile
» est exécuté à chaque ouverture de session. Il est donc nécessaire de se (re)connecter pour que les modifications soient prises en compte dans chaque terminal lancé. Pour cette séance, vous pouvez vous contenter de recharger le fichier de configuration avec la commande «source ~/.profile
».Si vous souhaitez profiter immédiatement des bénéfices de la modifications du fichier «
.profile
», vous devez vous déconnecter de la machine et vous reconnecter. - Vérifiez le bon fonctionnement de l'exécutable «
symfony
»symfony self:version
- Contrôlez la compatibilité du système avec la commande :
symfony check:requirements --verbose
Symfony Requirements Checker ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > PHP is using the following php.ini file: /etc/php/8.3/cli/php.ini > Checking Symfony requirements: [OK] iconv() must be available [OK] json_encode() must be available [OK] session_start() must be available [OK] ctype_alpha() must be available [OK] token_get_all() must be available [OK] simplexml_import_dom() must be available [OK] detect_unicode must be disabled in php.ini [OK] xdebug.show_exception_trace must be disabled in php.ini [OK] xdebug.scream must be disabled in php.ini [OK] PCRE extension must be available [OK] string functions should not be overloaded [OK] xdebug.max_nesting_level should be above 100 in php.ini [OK] PCRE extension should be at least version 8.0 (10.42 installed) [OK] PHP-DOM and PHP-XML modules should be installed [OK] mb_strlen() should be available [OK] utf8_decode() should be available [OK] filter_var() should be available [OK] posix_isatty() should be available [OK] intl extension should be available [OK] intl extension should be correctly configured [OK] intl ICU version should be at least 4+ [OK] intl.error_level should be 0 in php.ini [OK] a PHP accelerator should be installed [OK] short_open_tag should be disabled in php.ini [OK] magic_quotes_gpc should be disabled in php.ini [OK] register_globals should be disabled in php.ini [OK] session.auto_start should be disabled in php.ini [OK] xdebug.max_nesting_level should be above 100 in php.ini [OK] "memory_limit" should be greater than "post_max_size". [OK] "post_max_size" should be greater than "upload_max_filesize". [OK] PDO should be installed [OK] PDO should have some drivers installed (currently available: mysql, pgsql, sqlite) [OK] Your system is ready to run Symfony projects Note The command console can use a different php.ini file ~~~~ than the one used by your web server. Please check that both the console and the web server are using the same PHP version and configuration.
InformationDans un environnement Windows, vous pouvez télécharger une archive
zip
qui contient «symfony.exe
». Ce programme est l'exécutable de l'outil que vous devez donc placer dans un répertoire de votre système et le rendre accessible en ligne de commande (le répertoire doit figurer dans la variable d'environnement «Path
»).
Création d'un projet Symfony
¶
Vous allez pouvoir créer un projet Symfony
à l'aide de l'outil « symfony
» en ligne de commande (« Symfony CLI »).
Travail à réaliser
- Si ce n'est pas déjà fait, installez
Composer
InformationL'outil «
symfony
» en ligne de commande (« Symfony CLI ») utiliseComposer
pour créer le nouveau projet. S'il n'est pas disponible sur le système, une version temporaire sera téléchargée. Il est plus rapide et logique d'avoir votre propre version fonctionnelle qui sera par ailleurs utile par la suite. - Vérifiez que
Composer
fonctionne correctement :composer about
- Mettez à jour
Composer
:composer self-update
- Vérifiez que vous êtes bien dans le répertoire «
/working/votre_login
» (ou n'importe quel répertoire de votre choix si vous êtes sur votre ordinateur personnel) - Lancez la création d'un nouveau projet
Symfony
version «7.3.*
» :symfony --version 7.3 --webapp new symfony-contacts
Vérification du bon fonctionnement de l'application ¶
Si vous avez réalisé toutes les étapes précédentes sans encombre, l'application doit fonctionner. Vous allez donc le vérifier. Vous allez utiliser l'environnement de développement de Symfony
qui est celui qui est activé par défaut en mode développement.
Travail à réaliser
- Placez-vous le répertoire de l'application
- Dans le terminal, lancez le serveur Web local avec la commande suivante :
symfony serve
InformationLe serveur Web fonctionnera tant que vous n'aurez pas terminé l'exécution l'outil ligne de commande «
symfony
» avec «CTRL+C
». - Suivez les instructions données dans la partie « Gestion du certificat du serveur Web de l'API dans le navigateur » du tutoriel « Configuration CORS pour utiliser l'authentification de l'API avec React »
- Accédez à l'URL «
https://127.0.0.1:8000
» pour obtenir : - Constatez l'apparition de la Web Debug Toolbar
- Observez les sorties texte du serveur Web local
- Naviguez rapidement à travers les outils de la Web Debug Toolbar
- Observez les sorties texte du serveur Web local
- Terminez l'exécution de l'outil ligne de commande «
symfony
» avec «CTRL+C
»
Gestion des versions avec Git ¶
Afin de fiabiliser votre méthode de développement, vous allez utiliser Git
pour gérer le suivi des versions de l'application Symfony
.
Dépôt local ¶
Vous allez configurer le dépôt Git
local.
Travail à réaliser
- Assurez-vous d'être dans le répertoire du projet
symfony-contacts
- Constatez que le dépôt
Git
local a été initialisé par l'outil «symfony
» en ligne de commande (« Symfony CLI »)git log
- Excluez du suivi de
Git
le répertoire «.idea
» dePhpStorm
echo -e "\n/.idea/" >> .gitignore
git add .gitignore
git commit -m "Exclusion du répertoire .idea"
Information
Si vous créez le projet avec Composer
, vous devez effectuer les actions suivantes :
- Initialisez le dépôt
Git
git init
- Ajoutez l'ensemble des fichiers à l'index
git add .
- Effectuez la première validation
git commit -m "Initial commit"
- Renommez la branche principale en «
main
» (une branche vide ne peut pas être renommée, c'est pourquoi ceci est fait après le premier «commit
»)git branch -m main
Dépôt distant ¶
Passons maintenant à la configuration du dépôt distant.
Travail à réaliser
- Créez un nouveau projet «
symfony-contacts
» surGitLab
(pensez à décocher la case « Initialize repository with a README ») - Associez le dépôt local et le dépôt distant
- Poussez la branche locale
Remarque importante
Dans toute la suite du TP, pensez à effectuer des « commit
» réguliers (un par question au minimum).
Vous pouvez utiliser PhpStorm
pour les commandes Git
« commit
» et « push
». PhpStorm
propose une option « Commit and Push… » particulièrement adaptée à votre situation :
N'oubliez pas d'ajouter les nouveaux fichiers au gestionnaire de versions (Ctrl+Alt+A
) avant vos « commit
». Vous pouvez constater que le nom des fichiers s'affiche en vert pour ceux qui ont été ajoutés au suivi par opposition au rouge pour ce qui n'ont pas été ajoutés et gris clair pour ceux qui sont ignorés.
Création du projet dans PhpStorm
¶
La gestion d'une application Symfony
nécessitant de modifier de nombreux fichiers dans une arborescence complexe, vous utiliserez PhpStorm
pour l'édition de texte. Des greffons apportent le support de Symfony
, Composer
, des fichiers YAML
, Twig
, … Certains sont préinstallés dans la configuration générale.
Vous allez créer un nouveau projet PHP
à partir de PhpStorm
pour gérer l'application Web.
Remarque importante
PhpStorm
est un outil puissant parmi d'autres développés par JetBrains. Leur utilisation dans le cadre professionnel impose de s'acquitter d'une licence annuelle. Cependant, dans la cadre universitaire, vous pouvez disposer d'une licence gratuite pour les étudiants. Ceci vous permet d'utiliser les outils sur votre ordinateur personnel, tant que vous êtes étudiant. L'utilisation de PhpStorm
au sein du département ne nécessite pas de démarche particulière puisque nous avons un serveur de licences JetBrains.
Je vous invite néanmoins à demander une licence et à travailler sur votre ordinateur personnel en dehors des séances de TP.
Travail à réaliser
- Dans le terminal et dans le répertoire du projet, lancez la commande
phpstorm . &
InformationCette commande est la façon la plus simple et la plus rapide de créer un nouveau projet
PhpStorm
dans un répertoire. Il n'est pas utile de la lancer une fois le projet créé puisque vos anciens projets sont proposés à l'ouverture dePhpStorm
ou dans son menu « File » puis « Recent Projects ». - Patientez pendant l'indexation des fichiers du projet visible dans la partie droite de la barre d'état
- Activez le greffon «
Symfony Support
» si ce n'était pas déjà fait et que cela vous est proposé
Outils de qualité de code (analyse statique de code) ¶
Vous allez mettre en place des outils d'analyse statique de code pour garantir la qualité de l'application. Comme l'année dernière, vous utiliserez PHP CS Fixer
pour vérifier et corriger le style de le code PHP
. Vous utiliserez un outil équivalent pour le code Twig
.
Travail à réaliser
- Installez
PHP CS Fixer
en vous référant au tutoriel Installation et configuration dePhpStorm
pour configurerPHP CS Fixer
- Rendez-vous dans les préférences de
PhpStorm
dans « PHP → Quality Tools » et vérifiez quePHP CS Fixer
est bien configuré - Installez
Twig CS Fixer
, en pensant à exécuter la recette (recipe) :composer require --dev vincentlanglet/twig-cs-fixer ./composer.json has been updated Running composer update vincentlanglet/twig-cs-fixer Loading composer repositories with package information Updating dependencies Nothing to modify in lock file Writing lock file Installing dependencies from lock file (including require-dev) Nothing to install, update or remove Generating autoload files 123 packages you are using are looking for funding. Use the `composer fund` command to find out more! Symfony operations: 1 recipe (dffb4f3dfb06b7c1bbc163a1f4fd34f6) - WARNING vincentlanglet/twig-cs-fixer (>=3.0): From github.com/symfony/recipes-contrib:main The recipe for this package comes from the "contrib" repository, which is open to community contributions. Review the recipe at https://github.com/symfony/recipes-contrib/tree/main/vincentlanglet/twig-cs-fixer/3.0 Do you want to execute this recipe? [y] Yes [n] No [a] Yes for all packages, only for the current installation session [p] Yes permanently, never ask again for this project (defaults to n): y <-- répondre "y" ici - Configuring vincentlanglet/twig-cs-fixer (>=3.0): From github.com/symfony/recipes-contrib:main Executing script cache:clear [OK] Executing script assets:install public [OK] Executing script importmap:install [OK] What's next? Some files have been created and/or updated to configure your new packages. Please review, edit and commit them: these files are yours. vincentlanglet/twig-cs-fixer instructions: You can create a `.twig-cs-fixer.dist.php` and configure to your needs See https://github.com/VincentLanglet/Twig-CS-Fixer/blob/main/docs/configuration.md For configuration explanation. No security vulnerability advisories found. Using version ^3.9 for vincentlanglet/twig-cs-fixer
Documentation du projet ¶
Tout projet de développement doit fournir les clés pour l'installation, la configuration et le démarrage par un nouveau développeur. Cet effort de documentation peut également s'avérer bénéfique pour le créateur du projet qui peut oublier certains points essentiels de configuration au fil du temps. Ainsi, vous allez rédiger le mode d'emploi du projet dans un fichier « REAMDE.md
» et le tenir à jour au fil du développement.
Travail à réaliser
- Créez le fichier «
README.md
» à l'aide dePhpStorm
(qui vous propose de l'ajouter à l'indexGit
) - Complétez les informations suivantes :
- un titre de niveau 1 contenant le titre explicite du projet
- un titre de niveau 2 « Auteur(s) » vous permettant de préciser votre nom et votre prénom (ainsi que ceux de votre binôme, le cas échéant)
- un titre de niveau 2 « Installation / Configuration » précisant les points essentiels permettant d'installer, de configurer et de lancer le projet
- Validez votre travail dans
Git
Mise en place de scripts Composer
¶
Les dépendances du projet Symfony
sont gérées par Composer
. Profitons-en pour mettre en place quelques scripts Composer
qui faciliteront la gestion quotidienne du projet.
Travail à réaliser
- Ajoutez un script «
start
» qui lance le serveur web de test («symfony serve
») sans restriction de durée d'exécution - Ajoutez un script «
test:phpcs
» qui lance la commande de vérification du code parPHP CS Fixer
- Ajoutez un script «
fix:phpcs
» qui lance la commande de correction du code parPHP CS Fixer
- Ajoutez un script «
test:twigcs
» qui lance la commande de vérification du code parTwig CS Fixer
- Ajoutez un script «
fix:twigcs
» qui lance la commande de correction du code parTwig CS Fixer
- Ajoutez un script «
test
» qui lance les scripts Composer «test:phpcs
» et «test:twigcs
» - Ajoutez un script «
fix
» qui lance les scripts Composer «fix:phpcs
» et «fix:twigcs
» - Documentez vos scripts dans le fichier «
composer.json
» - Documentez vos scripts dans le fichier «
README.md
» - Validez votre travail dans
Git
- Relancez le serveur Web local à l'aide du script
Composer
que vous venez d'écrire
Désactivation de Symfony UX Turbo
¶
Depuis plusieurs versions de Symfony
, Symfony UX Turbo
est activé par défaut. Ce « bundle », faisant partie de l'initiative Symfony UX
, apporte le support de Hotwire Turbo
qui amène une expérience utilisateur de type application web monopage (SPA en anglais) sans avoir à écrire de Javascript
. Le principal avantage est que les ressources liées (images, fichiers JavaScript
, fichiers CSS
, …) à la ressource principale (celle affichée dans la barre d'adresse du navigateur) ne sont pas rechargées à chaque changement d'URL. Ceci accélère significativement les temps de chargement et diminue la bande passante nécessaire. Cependant, dans le cadre de l'apprentissage des mécaniques Web, le fonctionnement de Hotwire Turbo
transforme les intéractions client/serveur et perturbe votre compréhension du fonctionnement de Symfony
. Vous allez donc le désactiver..
Travail à réaliser
- Ouvrez le fichier «
assets/controllers.json
» - Désactivez le contrôleur
Stimulus
«@symfony/ux-turbo
» en passant la valeur de l'attribut «enabled
» à «false
»:{ "controllers": { "@symfony/ux-turbo": { "turbo-core": { "enabled": false, "fetch": "eager" …
Le routeur ¶
Dans le framework Symfony
, un unique programme « public/index.php
» est lancé pour chaque requête HTTP
vers l'application et il est dépendant de l'environnement, par défaut « dev
» pour développement et « prod
» pour production. Le système de routage entre alors en jeu pour permettre de réaliser des tâches différentes en fonction de la requête HTTP
soumise à l'application.
Travail à réaliser
Lisez les premiers paragraphes de la documentation sur le routage jusqu'à la fin de « Creating Routes as Attributes » et faites le lien avec la représentation graphique du flux applicatif :
Les routes actuelles ¶
Les routes disponibles sont potentiellement différentes en fonction de l'environnement de l'application. Il existe, par défaut, des routes accessibles dans les environnements « prod
» et « dev
» et des routes spécifiques à l'environnement de développement.
Travail à réaliser
- Observez les routes disponibles dans l'environnement de production :
bin/console debug:router --env=prod
- Observez la configuration générale du routage en ouvrant le fichier «
config/routes.yaml
» qui décrit que le routage est défini dans les attributs de vos contrôleurs - Observez les routes disponibles dans l'environnement de développement, qui est celui par défaut dans la configuration :
bin/console debug:router
Les routes disponibles dans l'environnement de développement sont actuellement, dans cet ordre :
- Une route pour les erreurs
Twig
- une route «
_wdt
» qui correspondent à la « Web Debug Toolbar » - celles commençant par «
_profiler
» qui sont destinée au « Profiler » (profilage de l'application lors de son exécution)
- Une route pour les erreurs
- Observez la configuration du routage « Profiler » en ouvrant le fichier «
config/routes/web_profiler.yaml
» - Vous constatez que les routes sont définies dans la configuration du «
WebProfilerBundle
» et uniquement dans l'environnement de développement avec «when@dev
» en début de configuration
Liens entre route et contrôleur ¶
Chaque route définie permet de déclencher une action d'un contrôleur (« Controller
»). Une action est une méthode publique d'un contrôleur qui est associée à une URI
, généralement à l'aide d'un attribut « Route
» qui précède la méthode.
Les fichiers des contrôleurs sont localisés dans le répertoire « Controller
» et sont nommés « xxxController.php
», « xxx
» étant le nom du contrôleur. Les contrôleurs font partie de l'espace de nom « App\Controller
» ou d'un sous espace de nom de ce dernier. Ils héritent possiblement de « Symfony\Bundle\FrameworkBundle\Controller\AbstractController
».
Travail à réaliser
- Complétez vos connaissances en lisant au moins la partie « Creating Routes as Attributes » de la documentation.
- Créez un nouveau contrôleur «
HelloController
» à l'aide du « MakerBundle » :bin/console make:controller Hello
InformationLe «
MakerBundle
» peut fonctionner en mode interactif ou à l'aide de paramètres de la ligne de commande. Ici, vous avez fourni le paramètre «Hello
» qui correspond au nom du contrôleur que vous souhaitez. Ce dernier sera donc nommé «HelloController
» car le «MakerBundle
» ajoute automatiquement le suffixe «Controller
» que vous n'aviez pas précisé. - Ouvrez le fichier du contrôleur dans
PhpStorm
- Observez l'ensemble des routes disponibles pour l'application avec la commande
bin/console debug:router
- Observez l'ensemble des routes disponibles pour l'application ainsi que les contrôleurs associés avec la commande
bin/console debug:router --show-controllers
- Faites le lien entre la première route disponible et le code généré par le «
MakerBundle
» - Observez les détails de la route nommée «
app_hello
» grâce à la commandebin/console debug:router app_hello
- Ajoutez l'action et la route associée qui suivent dans le contrôleur :
#[Route('/hello/world')] public function world(): Response { return new Response('Hello world!'); }
- Notez que cette route ne comporte pas de nom dans l'attribut «
#[Route(
» et faites le lien avec le nom généré automatiquement que vous observez à l'aide de la commandebin/console debug:router
- Essayez l'URL «
http://localhost:8000/hello/world
» - Regardez le code source
HTML
du contenu reçu par le navigateur - Essayez l'URL «
http://localhost:8000/hello/guys
» - Constatez la réponse reçue par le navigateur et son code
HTTP
Route contenant un paramètre ¶
Les routes ne sont pas nécessairement définies à partir d'un URI
fixe qui permet de déclencher une action d'un contrôleur. Il est en effet possible de rendre paramétriques des parties de l'URI
.
Travail à réaliser
- Complétez vos connaissances en lisant au moins la partie « Route Parameters » de la documentation.
- Remplacez le texte «
world
» du chemin «/hello/world
» de la route par un paramètre «name
» - Adaptez le prototype de l'action «
world()
» afin qu'elle puisse recevoir la valeur du paramètre «name
» de la route - Observez la nouvelle formulation de la route de l'application avec la commande
bin/console debug:router
- Remplacez le mot «
world
» de la chaîne «Hello world!
» par la valeur du paramètre de l'actionInformationCe que vous venez de faire est extrêmement dangereux puisque toute chaîne fournie dans l'
URL
va se retrouver directement dans la réponse envoyée au navigateur, constituant ainsi une possibilité d'attaque XSS reflétée. Il faudrait échapper la valeur de la variable «$name
», comme cela vous a déjà été démontré à plusieurs reprises dans les précédents sujets de TP. - Essayez l'
URL
«http://localhost:8000/hello/world
» - Essayez l'
URL
«http://localhost:8000/hello/bob
» - Constatez la réponse reçue par le navigateur et son code
HTTP
- Remarquez le lien entre le paramètre «
name
» du chemin de la route et le paramètre «$name
» de l'action
Les vues dans Symfony
: Twig
¶
Maintenant que vous avez rendu paramétrique l'action world()
du contrôleur HelloController
, vous allez lui associer le rendu d'une vue Twig
.
Web Debug Toolbar ¶
La « Web Debug Toolbar » n'est activée que si la vue contient la balise de fin de corps d'une page Web </body>
.
Travail à réaliser
- Saisissez l'
URL
«http://localhost:8000/hello/world
» dans le navigateur - Dans l'action «
world()
» du «HelloController
», demandez le rendu d'un modèleTwig
en remplaçant l'instructionreturn new Response('…
parreturn $this->render('hello/world.html.twig');
- Essayez l'
URL
«http://localhost:8000/hello/world
» - Constatez l'erreur signalée par
Symfony
ainsi que le code réponseHTTP
reçu par le navigateur - Créez le fichier «
world.html.twig
» manuellement en effectuant un clic droit sur le répertoire «templates/hello
» dansPhpStorm
et en utilisant le menu « New » puis « File » - Essayez l'
URL
«http://localhost:8000/hello/world
» - Constatez la réponse vide reçue par le navigateur
- Ajoutez le texte «
Hello world!
» dans le fichier «templates/hello/world.html.twig
» - Essayez l'
URL
http://localhost:8000/hello/world
- Constatez que la « Web Debug Toolbar » n'est pas présente
- Regardez le code source
HTML
du contenu reçu par le navigateur - Faites en sorte que le fichier «
templates/hello/world.html.twig
» propose une structureHTML
correcte dont le titre sera «Hello World!
» et qui contiendra le paragraphe «Hello World!
» - Essayez l'
URL
«http://localhost:8000/hello/world
» - Notez l'apparition de la « Web Debug Toolbar ».
- Cliquez sur un des éléments de la « Web Debug Toolbar » pour accéder au profileur
- Naviguez dans les pages du profileur afin d'en découvrir les possibilités
Transmettre des données à la vue ¶
La vue a pour objectif de présenter les données à l'utilisateur. Vous allez donc découvrir comment transmettre des données au modèle Twig
et comment les exploiter.
Travail à réaliser
- Saisissez l'
URL
«http://localhost:8000/hello/bob
» dans le navigateur - Lisez et observez les exemples de « Rendering Templates » et « Creating Templates »
- Passez la valeur du paramètre de l'action à la vue Information
Vous avez remarqué que le paramètre du chemin de la route «
{name}
» se retrouve sous le même nom «$name
» comme paramètre de l'action (et c'est d'ailleurs par rapport au nom queSymfony
fait « automagiquement » la correspondance entre les deux). Lorsque vous passez la même valeur à la vue, vous devez choisir le nom sous lequel la donnée sera manipulée dans le modèleTwig
. Afin de maintenir une logique globale et faciliter la compréhension du code, il est vivement conseillé de préserver le même nom pour l'utilisation dans le modèleTwig
. - Utilisez la valeur dans la vue pour produire «
Hello la_valeur_du_paramètre!
» dans le titre du documentHTML
et dans le paragraphe - Vérifiez le bon fonctionnement de cette nouvelle version de la vue dans le navigateur Web
- Saisissez l'
URL
«http://localhost:8000/hello/bob<script>
» dans le navigateur (oui, il y a bien «<script>
» à la fin de l'URL
!) - Observez le résultat dans le navigateur
- Observez le code source
HTML
du résultat dans le navigateurInformationTwig
échappe automatiquement les valeurs générées avec «{{ }}
» dans les « templates ».
Héritage et inclusion de « templates » Twig
¶
Vous venez de réaliser une vue à l'aide de « templates » Twig
. Cependant, la constitution de plusieurs vues ne devrait pas demander d'écrire une page Web complète pour chacune d'entre elles. Il est possible d'éviter ce genre de répétition en utilisant l'héritage ou l'inclusion de « templates ». Pour y parvenir, il convient de respecter les conventions de nommage et d'emplacement des modèle Twig
.
Travail à réaliser
- Modifiez la vue «
world.html.twig
» afin qu'elle hérite de «base.html.twig
» - Remplacez la structure
HTML
du modèle par l'utilisation des blocs définis dans «base.html.twig
»InformationProfitez des suggestions de
PhpStorm
pour retrouver simplement les noms des blocs disponibles hérités du modèle «base.html.twig
». - Accédez à «
http://localhost:8000/hello/bob
» - Vérifiez le code source du résultat dans le navigateur
- Constatez tous les éléments
CSS
etJavaScript
ajoutés au code source final par l'héritage
Prise en main rapide de Twig
¶
Vous allez explorer quelques-unes des possibilités offertes par Twig
.
Travail à réaliser
- Utilisez une structure algorithmique
Twig
«for
» pour afficher 10 fois le paragraphe de salutation dans le nouveau « template » - Modifiez le texte produit pour y inclure le numéro du tour de boucle de
1
à10
en fin de ligne (le résultat est donc de la forme «Hello bob! (6)
») - Utilisez la fonction «
cycle
» deTwig
pour afficher alternativement en rouge puis vert (un attributHTML
«style=""
» suffira pour cet essai. - Ajoutez un filtre sur le nom afin qu'il apparaisse avec la première lettre en majuscule
- Installez le paquet
Composer
«twig/intl-extra
» pour bénéficier des fonctions d'internationalisation deTwig
- Formatez le nombre de
1
à10
pour qu'il soit systématiquement affiché sur deux caractères
De la route à la vue ¶
Vous allez créer une nouvelle route, une nouvelle action dans le contrôleur ainsi qu'un nouveau « template » Twig
associé. L'action permettra d'afficher le message de salutation un nombre de fois donné.
Création d'une nouvelle route ¶
Vous allez ajouter une nouvelle route pour découvrir de nouvelles possibilités du routeur de Symfony
.
Travail à réaliser
- Consultez les règles de bonnes pratiques concernant les contrôleurs
- Créer une action vide «
manyTimes()
» dans le contrôleur «HelloController
»InformationEn saisissant «
pubf
» suivi de «TAB
» dans une classe,PhpStorm
génère automatiquementpublic function () { }
Vous êtes alors prêt à saisir le nom de la méthode et un nouvel appui sur
TAB
fait passer le focus sur la saisie des paramètres de la méthode. - Associez une route de chemin «
/hello/name/times
» paramétré par «name
» et «times
» à cette action en ajoutant l'attribut «#[Route(…
» - Si vous décidez de nommer la route, utilisez le nommage standard «
app_nomducontroleur_nomdelaction
» (c'est un exemple !) - Modifiez l'action pour que ses paramètres soient en accord avec ceux du chemin de la route
- Consultez les règles de bonnes pratiques concernant le nommage des modèles
Twig
- Retournez le résultat la méthode «
render()
» du modèle «hello/many_times.html.twig
» - Utilisez les suggestions de
PhpStorm
(«Alt+Entrée
») pour générer automatiquement ce nouveau modèle :Remarque importanteSi la génération automatique du « template » n'est pas proposée par
PhpStorm
, c'est que vous n'avez pas installé le pluginSymfony
:que vous ne l'avez pas activé lorsque cela vous a été proposé :
ou qu'il n'est pas actif pour ce projet :
- Modifiez le code
Twig
en prenant «world.html.twig
» comme base :- Remplacez le titre de la page Web par «
Hello many times!
» - Remplacez le paragraphe de salutation par «
Hello many times valeur_du_paramètre_name!
» - Remplacez l'alternance des couleurs par une alternance entre bleu et orange
- Affichez «
times
» fois le paragraphe de salutation
- Remplacez le titre de la page Web par «
- Essayez l'
URL
«http://localhost:8000/hello/bob/5
» et vérifiez le bon fonctionnement
Ajout de conditions sur les paramètres ¶
Le routage de Symfony
permet de vérifier que les paramètres répondent à certaines conditions pour pouvoir déclencher une route.
Travail à réaliser
- Complétez la route pour que son second paramètre
times
soit un chiffre en utilisant la validation de paramètres - Essayez l'
URL
«http://localhost:8000/hello/bob/five
» et vérifiez que la validation du paramètre «times
» fonctionne (et donc que la route n'est pas acceptée !) - Vérifiez dans l'action du contrôleur que «
times
» est bien différent de zéro et inférieur ou égal à 10. Fixez sa valeur à 3 dans le cas contraire - Essayez les URL «
http://localhost:8000/hello/bob/5
», «http://localhost:8000/hello/bob/0
» ainsi que «http://localhost:8000/hello/bob/42
» et vérifiez la cohérence du résultat produit - Rendez le paramètre «
times
» optionnel qui vaudra par défaut «3
». - Utilisez la « Web Debug Toolbar » pour visualiser quelle est la route déclenchée par l'
URL
«http://localhost:8000/hello/bob
» - Faîtes en sorte que ce soit la route «
app_hello_manytimes
» qui soit déclenchée par l'URL
«http://localhost:8000/hello/bob
» (ceci doit mettre en évidence la façon dont les routes sont étudiées parSymfony
)
Redirection dans le contrôleur ¶
Les contrôles que vous venez d'effectuer conduisent à une forme d'incohérence de l'application. En effet, si vous demandez l'URL
« /hello/bob/42
», les conditions ajoutées dans le contrôleur vont limiter l'affichage à 3 messages alors que l'URL
contient toujours « 42
». Il serait souhaitable dans ce cas que le « 42
» de l'URL soit remplacé par « 3
». En raisonnant du côté serveur, il faut donc effectuer une première réponse à la requête de « /hello/bob/42
» qui demande une redirection vers « /hello/bob/3
» afin que le navigateur effectue une nouvelle demande de ressource, correcte cette fois.
Travail à réaliser
- Observez l'incohérence entre l'«
URL
» «/hello/bob/42
» demandée et les 3 messages affichés dans le navigateur - Lisez le chapitre concernant les redirections
- Effectuez une redirection dans l'action «
manyTimes()
» en demandant seulement «3
» affichages lorsque le paramètre «times
» est hors des bornes fixées précédemmentInformationSi vous tapez les guillemets du premier paramètre de la méthode «
redirectToRoute()
»,PhpStorm
doit vous proposer la liste de routes disponibles. - Vérifiez le fonctionnement en observant la redirection de «
/hello/bob/42
» dans la barre de développement de le navigateur (pensez à cocher « Preserve log » pour pouvoir visualiser la réponse de redirection)
De la vue à la route ¶
Symfony
et son modèle de routeur prévoient de ne jamais écrire manuellement des URL
vers les ressources de l'application. Les URL
doivent être produites automatiquement en Twig
en se basant sur le nom de la route correspondant à l'URL
souhaitée.
Travail à réaliser
- Faites le ménage dans l'action «
index()
» qui avait été générée par le «MakerBundle
» dans le contrôleur «HelloController
» pour ne préserver que le rendu de la vue - Faites également le ménage dans le modèle associé «
hello/index.html.twig
» en supprimant le contenu de tous les blocs hormis le titre - Consultez les règles de production de liens vers des ressources de l'application
- Dans une liste à puces, créez un lien relatif qui permet de produire le résultat de «
5
» « Hello » à «Joe
»InformationPhpStorm
peut vous proposer les routes existantes dans les fonctionsTwig
«path()
» ou «url()
», profitez-en. - Dans la liste à puces, ajoutez un lien absolu qui permet de produire le résultat de «
8
» « Hello » à «Bob
» - Vérifiez le bon fonctionnement de vos liens
- Vérifiez que vos deux liens sont bien respectivement relatif et absolu en observant le code
HTML
reçu par le navigateur
Introduction aux tests fonctionnels ¶
Vous avez été sensibilisés aux tests pendant le « TP Développement d'une application Web de consultation et modification de morceaux de musique ». Vous avez certainement remarqué le répertoire « tests
» dans l'arborescence de Symfony
. Il contiendra les tests unitaires, d'intégration ou fonctionnels associés à vos classes.
Symfony
est nativement prévu pour fonctionner avec PHPUnit
grâce au « PHPUnit Bridge ». Pour des raisons de simplicité d'écriture et de facilité de compréhension, nous utiliserons plutôt Codeception
qui possède un module pour Symfony
.
Installation et configuration de Codeception
¶
Travail à réaliser
- Installez
Codeception
et ses modules «asserts
» et «symfony
» à l'aide deComposer
:composer require --dev --no-interaction codeception/codeception codeception/module-asserts codeception/module-symfony
InformationL'option «
--no-interaction
» permet d'éviter toute interaction lors de l'installation. Dans ce cas particulier, il ne vous sera donc pas demandé si vous souhaitez appliquer les recettesFlex
deCodeception
. Si toutefois la question vous est tout de même posée, nous ne souhaitons pas les appliquer car cela crée de nombreux répertoires et fichiers dans «tests
» et nous n'en avons pas l'utilité. - Initialisez
Codeception
pour le projet :php vendor/bin/codecept bootstrap --namespace=App\\Tests --empty
- Chargez les paramètres de configuration de
Codeception
selon l'environnement deSymfony
en complétant le fichier «codeception.yml
» :params: - .env - .env.test
Tests de l'action « manyTimes()
» du contrôleur « HelloController
»
¶
Travail à réaliser
- Créez une nouvelle suite de tests que nous dédirons aux contrôleurs :
php vendor/bin/codecept generate:suite Controller
- Mettez au propre le source
PHP
généré :composer fix:phpcs
InformationLes scripts
Composer
peuvent être lancés en omettant une partie de leur nom, tant qu'il n'y a pas d'ambiguïté. Ici, «composer fix:p
» est équivalent à «composer fix:phpcs
». - Créez un «
Cest
» («Codecept
» + «Test
») dédié à l'action «manyTimes()
» du «HelloController
» :php vendor/bin/codecept generate:cest Controller Hello\\ManyTimes
InformationSi vous êtes sur
Windows
et que vous utilisez le terminalcmd
ouPowerShell
, le caractère « \ » n'a pas le même sens qu'en environnementLinux
ouMacOS
. Il n'est donc nécessaire de le doubler dans la ligne de commande. - Mettez au propre le source
PHP
généré :composer fix:phpcs
- Activez les modules «
Symfony
» et «Asserts
» de la suite «Controller
» en remplaçant la clé «modules
» dans le fichier «tests/Controller.suite.yml
» :modules: # enable helpers as array enabled: - Symfony: app_path: 'src' environment: 'test' - Asserts:
- Lancez la construction des classes «
Actor
» deCodeception
pour prendre en compte les nouveaux modules :php vendor/bin/codecept build
- Testez le style du code
PHP
:composer test:phpcs
InformationLes fichiers
PHP
dont le style n'est pas conforme sont générés parCodeception
et exclus du dépôtGit
. Il est donc nécessaire de modifier la configuration dePHP CS Fixer
pour qu'il n'essaie pas de les corriger. - Modifiez la configuration de
PHP CS Fixer
dans le fichier «.php-cs-fixer.dist.php
» pour exclure le répertoire «tests/Support/_generated
» - Testez de nouveau le style du code
PHP
pour vérifier que le répertoire est bien exclu de l'analyse : - Remplacez le fichier des tests du contrôleur par l'ensemble de tests «
ManyTimesCest.php
» (télécharger)InformationCes tests fournis sont assez détaillés pour que vous les utilisiez comme base d'exemple.
- Lancez les tests à l'aide de la commande
php vendor/bin/codecept run
- Vérifiez que le code passe les tests
Ajout de scripts Composer
pour lancer les tests
¶
Travail à réaliser
- Ouvrez le fichier «
composer.json
» - Ajoutez un script «
test:codeception
» qui- nettoie le répertoire «
_output
» et le code généré parCodeception
- lance les tests de
Codeception
- nettoie le répertoire «
- Complétez le script «
test
» pour qu'il lance le précédent script à la suite de ceux déjà présents - Décrivez ces scripts
Composer
dans «composer.json
» et dans la documentation du projet
Configuration de l'accès base de données de l'application ¶
Vous avez utilisé l'outil « symfony
» en ligne de commande pour créer le projet d'application Symfony
. Des valeurs par défaut ont été affectés à divers paramètres de configuration dans le fichier « .env
» situé à la racine du projet.
Remarque importante
Le fichier « .env
» sera inclus dans le dépôt Git
. Il est donc vital qu'il ne contienne pas vos mots de passe ! Il servira uniquement de base à la configuration en mentionnant les paramètres à définir. La configuration effective de l'application locale se fera dans le fichier « .env.local
». Ce dernier est par défaut exclu du gestionnaire de versions et doit le rester.
Travail à réaliser
- Dans le fichier «
.env
», observez les exemples de configuration de la base de données à travers les valeurs de la variable «DATABASE_URL
»InformationLes lignes commençant par «
#
» sont des commentaires et ne sont pas prises en compte dans la configuration. Elles servent ici à donner des exemples de configuration. - Afin de faciliter le travail de correction de votre production, modifiez la ligne en commentaire de la variable «
DATABASE_URL
» dans le fichier «.env
» pour qu'elle corresponde à une base de donnéesMariaDB
version 10.2.25# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
devientDATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.2.25-MariaDB&charset=utf8mb4" # DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=16&charset=utf8"
- Copiez le fichier «
.env
» en «.env.local
» à partir dePhpStorm
et ouvrez-le - Donnez les valeurs adéquates à la variable
DATABASE_URL
afin de vous connecter sur le serveur dont le nomDNS
est «mysql
» accessible avec l'utilisateur «web
» dont le mot de passe est «web
» (ou selon vos paramètres si vous êtes sur votre ordinateur personnel) pour accéder à la base de donnéesMySQL
(MariaDB 10.2.25
) nommée «cutron01_contact_demo
»InformationRetrouvez les parties constitutives d'une
URL
dans le sujet de TP sur le proptocoleHTTP
que vous avez réalisé en première année.Si vous souhaitez travailler sur votre ordinateur personnel, vous pouvez télécharger le script de création de la base de données (Clic droit puis « Enregistrer sous… »).
- Vérifiez l'accès à la base de données :
bin/console doctrine:query:sql "SELECT * FROM contact WHERE id=4"
Vous devriez obtenir une ligne de résultat :
---- ----------- ---------- ------------------------------ id firstname lastname email ---- ----------- ---------- ------------------------------ 4 Christine Michaud christine.michaud@raynaud.fr ---- ----------- ---------- ------------------------------
Consultation des contacts ¶
Le modèle de données étant à présent configuré, il est temps de l'utiliser. Pour cela, vous allez construire une nouvelle fonctionnalité de listage de l'ensemble des contacts de la base de données.
Modèle de données ¶
Symfony
intègre Doctrine
pour effectuer la persistance et l'accès aux données dans une base de données. L'interaction entre l'application et la base de données se fera à travers des objets PHP
appelés des entités qui constituent la logique métier de l'application ainsi que les relations entre les entités. Par convention, les définitions de ces classes seront localisées dans le répertoire src/Entity
.
Afin que ces classes puissent interagir avec le SGBD, il convient de définir les liens entre les objets PHP
et la base de données. Cette opération est qualifiée de « mapping » qui est décrit sous forme d'attributs PHP
dans la définition de la classe. Le « mapping » peut être réalisé manuellement ou de façon interactive à l'aide du « MakerBundle
».
Vous avez configuré l'application pour accéder à la base de données « cutron01_contact_demo
» :
Information
La démarche habituelle pour un projet Symfony
est de créer les entités et leurs relations en fonction des besoins révélés par la phase d'analyse, puis de créer la base de données à l'aide de Doctrine
, pour ensuite insérer des données factices qui permettent d'obtenir une application de démonstration pour le développement. Nous dérogeons temporairement à cette règle pour des raisons de progression pédagogique en vous fournissant une base de données qui contient déjà des données générées par nos soins.
Travail à réaliser
- Lisez le paragraphe « Creating an Entity Class »
- Utilisez le «
MakerBundle
» pour générer l'entité «Contact
» conformément à la tableMySQL
:bin/console make:entity Contact
en donnant les propriétés suivantes :- «
firstname
» de type «string
» de taille «30
» non «nullable
» - «
lastname
» de type «string
» de taille «40
» non «nullable
» - «
email
» de type «string
» de taille «100
» non «nullable
»
- «
- Actualisez la liste des fichiers du répertoire «
Entity
» par un clic droit sur la racine du projet puis « 🗘 Reload from disk » - Observez le fichier généré dans le répertoire «
src/Entity
» - Consultez la classe générée et expliquez les divers attributs
PHP
. - Observez le fichier généré dans le répertoire «
src/Repository
»
Liste des contacts ¶
Travail à réaliser
- Créez un nouveau contrôleur «
ContactController
» à l'aide du «MakerBundle
» - Lisez le chapitre « Récupérer des objets dans la base de données » de la documentation de
Symfony
- Supprimez tous les éléments inutiles de l'action et de la vue ainsi que les paramètres passés à la vue
- En paramètre de l'action «
index()
» générée par défaut, demandez le service «ContactRepository
» - Dans l'action, utilisez la méthode «
findBy()
» de la classe «EntityRepository
» afin de récupérer l'ensemble des contacts de la base de données (critère de sélection vide) par ordre alphabétique (tri ascendant sur le nom puis le prénom) - Transmettez l'ensemble des contacts à la vue
Twig
- Donnez un titre au contenu Web produit et proposez un titre de niveau 1 représentatif
- Dans la vue, effectuez le parcours de l'ensemble des contacts pour produire une liste à puces présentant chaque contact sous la forme « nom, prénom »
- Vérifiez que la liste s'affiche correctement
Tests fonctionnels ¶
Afin de poursuivre les tests fonctionnels, vous allez mettre en place des contrôles sur le résultat de la liste des contacts.
Information
La démarche des tests liés à la consultation de la base de données est ici incomplète (voire incorrecte) puisque nous nous appuyons sur la base de données de développement. Ceci vous permet néanmoins de prévoir les tests et la démarche sera rectifiée par la suite.
Travail à réaliser
- Copiez le fichier d'environnement de test «
.env.test
» en «.env.test.local
» - Définissez la variable contenant le chemin d'accès à la base de données comme dans l'environnement de développement
- Ajoutez ce nouveau fichier à la liste des paramètres de configuration de
Codeception
a> dans le fichier de configuration deCodeception
«codeception.yml
» - Mettez en commentaire la propriété «
dbname_suffix
» de «when@test.doctrine.dbal
» du fichier «config/packages/doctrine.yaml
» pour éviter d'ajouter «_test
» à la fin du nom de la base de données de test - Générez une classe de «
Cest
» pour l'action «index()
» du «ContactController
» :php vendor/bin/codecept generate:cest Controller Contact\\Index
- Supprimez les méthodes de la classe générée («
_before()
» n'est pas utile et «tryToTest()
» est un exemple) - Sur le modèle des tests présentés en début de TP, écrivez une méthode de test «
contactListContainsRightNumberOfContacts()
» permettant de contrôler que la ressource «/contact
» donne une réponseHTTP
200
et que le corps de la réponse vérifie que :- le titre de la page Web contient « Liste des contacts »
- un titre de niveau 1 contenant « Liste des contacts » est présent
- une liste à puce contient 195 éléments
InformationProfitez des suggestions de
PhpStorm
au fil de la saisie du code pour découvrir les méthodes à utiliser.
Remarque importante
Codeception
enregistre dans le répertoire « tests/_output
» le corps de la réponse HTTP
des ressources impliquées dans des tests échoués. Consultez ces contenus, ceci facilite grandement la recherche des erreurs !
Détails d'un contact, version naïve ¶
Vous allez à présent rechercher un contact pour afficher le détail de ses données. Cette recherche va s'effectuer de façon naïve à partir de l'identifiant du contact. Ceci permet de comprendre la mécanique et d'arriver en douceur au « ParamConverter
» dans la partie suivante.
Travail à réaliser
- Dans le contrôleur «
ContactController
», créez une action «show(int $contactId)
» qui reçoit en paramètre un identifiant de contact - Associez une route de chemin «
/contact/{contactId}
» à la nouvelle action - Appliquez les conditions requises à «
contactId
» - Dans la nouvelle action, demandez le rendu de la vue
Twig
«contact/show.html.twig
» - Générez le fichier
Twig
à l'aide dePhpStorm
- Vérifiez la bonne interaction de ces trois éléments
- En paramètre de l'action «
show()
», demandez le service «ContactRepository
» - Dans l'action, récupérez le contact concerné et transmettez-le à la vue
- Si le contact n'existe pas, levez une «
NotFoundHttpException
» dont le texte doit être explicite - Présentez le nom et le prénom du contact dans le titre du document
HTML
et dans un titre de niveau 1 - Présentez toutes les informations du contact (hormis l'identifiant) dans une liste de définitions
- Vérifiez que la route produit un résultat conforme
- Vérifiez que la route produit une réponse «
404
» pour un identifiant de contact qui n'existe pasInformationVous ajouterez des tests pour cette action dès que vous aurez des générateurs de données fictives.
Détails d'un contact, utilisation d'un « EntityValueResolver
»
¶
Vous allez à présent rechercher un contact en utilisant un « EntityValueResolver
» comme préconisé dans les bonnes pratiques. Cette démarche permet de simplifier le code.
Travail à réaliser
- Dans le contrôleur «
ContactController
», modifiez le chemin de la route «/contact/{contactId}
» pour que le nom du paramètre corresponde au nom de l'identifiant de l'entité «Contact
» - Modifiez les paramètres de l'action «
show()
» pour :- Remplacer l'identifiant de contact par un «
Contact
» - Supprimer le service «
ContactRepository
» qui sera inutile
- Remplacer l'identifiant de contact par un «
- Maintenez les conditions requises sur le paramètre du chemin de la route
- Supprimez le code maintenant inutile de l'action, en particulier le test
- Vérifiez que la route produit toujours un résultat conforme
- Vérifiez que la route produit une réponse «
404
» pour un identifiant de contact qui n'existe pas
Des routes pour produire des URL ¶
Vous venez de construire une liste de contacts et les détails d'un contact. Il convient à présent de rendre accessible les détails d'un contact par un clic sur son nom dans la liste des contacts. Vous n'écrirez pas d'URL
mais utiliserez les fonctionnalités Twig
permettant de les produire à votre place à partir du nom des routes.
Travail à réaliser
- Si nécessaire, relisez le chapitre « Linking to Pages » de la documentation
- Modifiez la vue «
contact/index.html.twig
» afin qu'elle propose à présent des liens vers les détails du contact sur chaque nom de contact - Vérifiez que les liens sont correctement produits et fonctionnels
- Améliorez le précédent test fonctionnel pour qu'il vérifie que la liste à puces contient 195 liens
- Écrivez un nouveau test permettant de cliquer sur le premier lien de la liste des contacts et de vérifier que la route obtenue est la bonne (sans tenir compte du paramètre de route)
Mise en place de votre propre base de données, retour aux bonnes pratiques ¶
Dans la partie précédente, vous avez consulté une base de données existante. La démarche habituelle lors de la création d'un projet Symfony
est de construire de nouvelles entités liées entre elles par des relations, de gérer des versions des entités et de la base de données et de remplir la base de données avec des données, factices ou non, permettant de faire fonctionner le projet complet directement après clonage. Vous allez donc à présent suivre cette démarche et apprendre à construire des données factices générées aléatoirement à partir de « Faker
».
Création de la base de données ¶
Avant de pouvoir créer la base de données, vous allez devoir modifier la configuration pour accéder à votre propre base de données MySQL
.
Travail à réaliser
- Ouvrez le fichier de la configuration locale du projet
- Modifiez la configuration base de données pour :
- Utiliser votre compte
MySQL
en lieu et place de l'utilisateur «web
» - Modifiez la base de données utilisée en «
votre_login_contact
» - Mettez la valeur du paramètre «
serverVersion
» en accord avec le serveurMySQL
du département, à savoir «mariadb-10.2.25
»InformationLa valeur de «
serverVersion
» doit impérativement être correcte pour que les migrations fonctionnent. En effet,MySQL
etMariaDB
n'ont pas la même façon d'accéder aux méta-informations de la base de données.
- Utiliser votre compte
- Lancez la création de la base de données :
bin/console doctrine:database:create
- Sur
phpMyAdmin
, vérifiez que la base a bien été créée
Création d'une migration de données ¶
Rappelons que vous avez créé une entité « Contact
». Cette entité n'est plus persistante, maintenant que la base de données de démonstration a été débranchée. Vous allez donc reprendre le cours normal de la création du projet en effectuant avec Doctrine
la synchronisation entre les entités et la base de données pour que la structure de la base de données soit équivalente à celle de l'ensemble des entités.
Puisque vos entités peuvent évoluer au fil des fonctionnalités développées, il est normal que la base de données évolue de la même façon. Cependant, contrairement à la base de données de développement qui peut être détruite sans danger, la base de données de production doit pouvoir être modifiée sans perte ni corruption de données. C'est l'objectif des migrations qui vont contenir les requêtes permettant de faire évoluer la base de données.
Travail à réaliser
- Lancez la construction de la première migration
bin/console make:migration
- Observez le contenu de la migration générée dans le répertoire «
migration
»
Création du schéma de la base de données ¶
Les migrations contiennent l'ensemble des requêtes SQL
permettant d'appliquer et de supprimer la mise à jour de la base de données à un instant donné de l'évolution du projet. Doctrine maintient l'état des migrations appliquées sur la base de données dans une table « doctrine_migration_versions
». Ainsi, la comparaison de l'ensemble des fichiers contenus dans le répertoire « migrations
» et du contenu de la table « doctrine_migration_versions
» permet de connaître les migrations à appliquer pour que la structure de la base de données soit à jour.
Travail à réaliser
- Lancez l'exécution des migrations
bin/console doctrine:migrations:migrate --no-interaction
- Sur
phpMyAdmin
, vérifiez la présence, la structure et le contenu de la table «doctrine_migration_versions
» - Vérifiez la présence, la structure et le contenu de la table «
contact
» - Vérifiez que l'affichage de la liste des contacts fonctionne toujours, mais ne contient aucun contact
Générateur de données factices ¶
Pour faciliter la démarche de remplissage de la base de données de développement, vous utiliserez les bundles « DoctrineFixturesBundle
» et « ZenstruckFoundryBundle
». Le premier permet de gérer la création de données factices (« fixtures
») avec Doctrine
. Le second propose de faciliter le processus de création d'une entité en définissant les valeurs par défaut des propriétés d'une nouvelle instance, souvent générées aléatoirement avec « Faker
». Par ailleurs, les méthodes « create*()
» des « Factory
» génèrent de nouvelles instances mais les font aussi persister automatiquement en base de données.
Travail à réaliser
- Utilisez
Composer
pour demander le bundle «orm-fixtures
» pour le développement (ne pas oublier l'option «--dev
» !) - Observez les nouveaux fichiers à l'aide de l'onglet « Commit » de
PhpStorm
- Effectuez un «
commit
» avec ces fichiers - Utilisez
Composer
pour demander le bundle «zenstruck/foundry
» pour le développement - Observez les nouveaux fichiers à l'aide de l'onglet « Commit » de
PhpStorm
- Effectuez un «
commit
» avec ces fichiers - Parcourez la documentation du «
DoctrineFixturesBundle
» - Lancez la création d'un générateur de données pour les contacts :
bin/console make:fixtures ContactFixtures
- Observez le contenu du fichier généré et supprimez le corps de la méthode «
load()
» qui sera complété dans quelques instantsInformationLe code d'exemple qui est proposé lors de la génération du fichier s'applique lorsque l'on utilise directement
Doctrine
. Puisque nous utilisons «Foundry
» pour nous faciliter la tâche, il est hors de propos. - Effectuez un «
commit
» avec ce fichier - Lisez le chapitre «
Generate
» et de la documentation de «Foundry
» - Lancez la création d'une nouvelle forge de données :
bin/console make:factory
- Observez le fichier généré
- Effectuez un «
commit
» avec ce fichier - Modifiez la méthode «
defaults()
» pour que :- le nom soit un nom de famille généré par «
Faker
» - le prénom soit un prénom généré par «
Faker
» - l'email soit de la forme «
prenom.nom@domain
», dans lequel le prénom et le nom sont en minuscule, sans caractères accentués et le domaine est un nom de domaine généré par «Faker
»InformationUne translittération «
'Any-Latin; Latin-ASCII'
» permet de supprimer tous les accents en remplaçant chaque caractère accentué par un caractère équivalent non accentué.Une translittération «
'Any-Lower; Latin-ASCII'
» permet de supprimer tous les accents en remplaçant chaque caractère accentué par un caractère minuscule équivalent non accentué.
- le nom soit un nom de famille généré par «
- Puisque certains noms de famille et certains prénoms composés contiennent des espaces incompatibles avec la structure d'une adresse email, il est plus sûr de remplacer tout caractère non alphabétique par un tiret
- Vous devez effectuer des traitements identiques sur le nom et sur le prénom de l'utilisateur en vue de construire son mail, proposez une méthode protégée «
normalizeName
» qui effectue ces traitements et qui sera utilisée par «defaults()
» - Votre méthode construit un «
Transliterator
» à chaque appel, ce qui est inutile et inefficace : construisez le «Transliterator
» dans le constructeur de la classe, stockez-le dans une propriété d'instance et utilisez-le dans «normalizeName()
» - Effectuez un «
commit
» avec ce fichier - Lisez les exemples du paragraphe « Using your Factory » de la documentation de «
Foundry
» - Modifiez le générateur de données de «
Contact
» pour qu'il crée 150 «Contact
» en utilisant la forge précédemment construiteInformationVous avez certainement envie de générer les données factices mais il va falloir attendre un peu !
Génération de la base de données et des données factices ¶
A ce stade, vous pourriez générer les données factices en base de données. Malheureusement, si vous avez commis des erreurs dans votre code et tentez de générer un nouveau jeu de données corrigé, elles vont se cumuler avec les anciennes. Pour palier ce problème, vous allez créer un script Composer
qui reprend toutes les étapes précédentes pour générer de façon fiable une nouvelle base de données contenant les données factices.
Travail à réaliser
- Créez un script
Composer
«db
» qui exécute les étapes suivantes :- Destruction forcée de la base de données
bin/console doctrine:database:drop --force --if-exists
- Création de la base de données
bin/console doctrine:database:create
- Application des migrations successives sans questions interactives
bin/console doctrine:migrations:migrate --no-interaction
- Génération des données factices sans questions interactives
bin/console doctrine:fixtures:load --no-interaction
- Destruction forcée de la base de données
- Documentez ce script dans le fichier «
composer.json
» - Documentez ce script dans le fichier «
README.md
» - Puisque cela n'a pas été fait auparavant, documentez la configuration de la base de données dans «
README.md
» - Lancez le script
Composer
«db
» - Observez le contenu de la table «
contact
» dansphpMyAdmin
- Réalisez le même type d'observation en utilisant la console, par exemple avec :
bin/console doctrine:query:sql "SELECT * FROM contact LIMIT 5"
InformationIl est essentiel de vérifier la pertinence de toutes les données générées. Il faut vérifier toutes les lignes et toutes les colonnes pour avoir une vision globale de la cohérence de ce qui est produit, aléatoirement ou pas.
- En vous inspirant de la documentation de «
Faker
» dans «Foundry
», modifiez la configuration de «Faker
» qui qu'il génère des textes en français - Réinitialisez la base de données et contrôlez les données produites qui doivent ressembler à :
bin/console doctrine:query:sql "SELECT * FROM contact LIMIT 5" ---- ----------- ----------- ------------------------------ id firstname lastname email ---- ----------- ----------- ------------------------------ 1 Édith Gregoire edith.gregoire@perez.com 2 Adélaïde Gauthier adelaide.gauthier@dupre.fr 3 Maurice Boulanger maurice.boulanger@allard.net 4 Louis Caron louis.caron@marty.org 5 Paulette Besnard paulette.besnard@rey.org ---- ----------- ----------- ------------------------------
- Vérifiez l'affichage de ces nouvelles données dans l'application
Tests fonctionnels basés sur des données factices ¶
Les tests fonctionnels dépendant de données ont précédemment été réalisés sur une version de démonstration de la base de données de développement. Ce principe est problématique puisqu'il nécessite un serveur de base de données MySQL
contenant des données et une connaissance du jeu de données. Habituellement, des données factices sont générées à la volée pour chaque test sur un moteur SQLite
qui ne nécessite pas d'infrastructure particulière.
Vous allez donc utiliser « Foundry
» pour générer des données factices lors des tests. Il faut installer le module « Doctrine
» de Codeception
pour pouvoir tester le contenu dans la base de données.
Travail à réaliser
- Ajoutez au projet la dépendance de développement au module «
codeception/module-doctrine
»composer require --dev codeception/module-doctrine
- Activez le module «
Doctrine
» dans la configuration de la suite des tests «Controller
» (fichier «tests/Controller.suite.yml
») - Activez l'option «
cleanup
» pour que chaque test s'exécute dans une transaction, empêchant ainsi les effets de bords - Ajoutez le fichier source de cet utilitaire («
Helper
») au projet en le plaçant dans le répertoire «tests/Support/Helper
» - Activez le «
Helper
» qui dépend du module «Symfony
» en ajoutant les lignes suivantes à la liste des modules activés dans le fichier «tests/Controller.suite.yml
» :- \App\Tests\Support\Helper\EntityManagerReset: depends: Symfony
InformationCe «
Helper
» permet de réinitialiser l'EntityManager
entre chaque test pour éviter les effets de bords. - Générez les classes «
Actor
» deCodeception
avec le nouveau module activé :php vendor/bin/codecept build
- Configurez l'accès à une base de données
SQLite
de test dans «.env.test
» en prenant tel quel le modèle proposé dans «.env
»InformationIl est classique de configurer une base de données
SQLite
pour les tests directement dans le fichier «.env.test
». - Supprimez le fichier «
.env.test.local
»rm .env.test.local
- Supprimez la référence à «
.env.test.local
» dans «codeception.yml
» - Modifiez le script
Composer
«test:codeception
» pour qu'il initialise la base de données de test avant de lancer les tests :- Nettoyage du répertoire «
_output
» et du code généré parCodeception
php vendor/bin/codecept clean
- Destruction silencieuse forcée de la base de données
bin/console doctrine:database:drop --force --quiet --env=test
- Création silencieuse de la base de données
bin/console doctrine:database:create --quiet --env=test
- Création silencieuse du schéma de la base de données
bin/console doctrine:schema:create --quiet --env=test
- Exécution des tests
Codeception
php vendor/bin/codecept run
- Nettoyage du répertoire «
- Documentez ce script dans le fichier «
composer.json
» - Documentez ce script dans le fichier «
README.md
» - Lancez le script
Composer
«test:codeception
» et constatez qu'il produit des erreurs - Mettez à jour le test de la liste des contacts en le débutant par la création de 5 «
Contact
» avec «ContactFactory
» - Ajoutez un test de clic sur le premier contact de la liste :
- À l'aide de «
ContactFactory
», créez un «Contact
» «Joe Aaaaaaaaaaaaaaa
» - Toujours à l'aide de «
ContactFactory
», créez 5 «Contact
» - Cliquez sur le lien «
Aaaaaaaaaaaaaaa, Joe
» - Vérifiez que la réponse est un succès
- Vérifiez que vous êtes sur la route «
app_contact_show
» avec les bonnes valeurs de paramètres
- À l'aide de «
- Ajoutez un test qui contrôle que les contacts sont correctement triés :
- Avec «
ContactFactory
», créez une séquence d'insertion de 5 «Contact
» dont deux ont le même nom de familleInformationPour que le test soit pertinent, utilisez des contacts dont les noms et prénoms sont fixés et insérés dans un ordre différent de l'ordre alphabétique attendu.
- Utilisez la méthode «
grabMultiple()
» du module «WebDriver
» deCodeception
pour récupérer la liste des contacts - Comparez l'ordre attendu et l'ordre constaté
- Avec «
- Vérifiez que le code passe tous les tests