TP n°4 - Programmation contrôleur Web Symfony
Code applicatif PHP déclenché en réponse aux requêtes HTTP
Table des matières
- 1. Introduction
- 2. Étape 1 : Exécution d’une application Web Symfony
- 2.1. TODO Étape 1-a : Lancement du serveur HTTP local sur l’application
ToDo
- 2.2. TODO Étape 1-b : Affichage des informations de mise-au-point dans la barre d’outils Symfony
- 2.3. TODO Étape 1-c : Accès réussi à une ressource de l’application
ToDo
- 2.4. TODO Étape 1-d : Examen de la table de routage de
ToDo
- 2.1. TODO Étape 1-a : Lancement du serveur HTTP local sur l’application
- 3. TODO Étape 2 : Examen du code du contrôleur HTTP de
ToDo
- 4. Étape 3 : Ajout d’un Contrôleur Web, dans Todo, pour les étiquettes
- 5. TODO Étape 4 : Ajout d’un Contrôleur Web dans le projet
- 6. Évaluation
- 7. TODO Ensuite, d’ici la semaine prochaine
1. Introduction
Cette séance vise à expérimenter la façon dont les programmes PHP sont invoqués
côté serveur pour traiter les requêtes émises par les clients.
On observera la mise en œuvre qui a été faite sur l’application « fil-rouge » ToDo
dans le framework
Symfony, avec un serveur PHP s’exécutant en local.
2. Étape 1 : Exécution d’une application Web Symfony
Cette étape permet de se familiariser avec la façon dont on peut tester le fonctionnement d’une application Symfony, en contexte Web, grâce à un serveur HTTP local.
Dans la version préparée en amont du cours, dont vous êtes partis, l’application « fil-rouge » ToDo dispose en effet, d’une interface pour HTTP, en plus de l’interface en ligne de commande que nous avons utilisée abondamment.
2.1. TODO Étape 1-a : Lancement du serveur HTTP local sur l’application ToDo
Démarrer le serveur Web local intégré à l’environnement de développement Symfony, pour pouvoir tester les interactions HTTP en local.
Lancez le serveur Web, comme déjà vu dans les séances précédentes :
cd $HOME/CSC4101/tp-02/todo-app/ symfony server:start
Dans la suite de la séance, vous allez tester l’exécution de
l’application « fil rouge » ToDo
dans un contexte Web.
Un serveur HTTP est lancé par l’utilitaire en ligne de commande Symfony. Il fonctionne grâce à un serveur HTTP embarqué par PHP.
Il permet de tester en local l’exécution du code de l’application Symfony présente dans le répertoire dans lequel il a été démarré.
L’application Web s’exécutera en « boucle », réagissant en réponse aux requêtes transmises à travers le serveur HTTP local.
L’intérêt en environnement de développement est que si vous mettez à jour le code, ces mises à jour seront prises en compte sans avoir à relancer le serveur HTTP.
Gardez le terminal ouvert avec le serveur lancé dedans, pour pouvoir consulter les logs sur la sortie affichée dans le terminal, au fur et à mesure de la mise-au-point.
2.2. TODO Étape 1-b : Affichage des informations de mise-au-point dans la barre d’outils Symfony
Explorer les fonctionnalités de la barre d’outils Symfony facilitant la mise-au-point au niveau du routage des requêtes vers les contrôleurs.
Consultez la page affichée pour http://localhost:8000/ dans le navigateur.
Remarquez la « barre d’outils » située en bas de page.
Figure 1 : Barre d’outils du développeur Symfony
Vérifiez ce qui se passe quand on place la souris au-dessus du code de réponse (404)
Remarquez le
Route name
« n/a » affiché dans le « pop-up »Cliquez sur cette case avec le code de retour. Une page s’affiche qui donne des détails sur le contexte d’exécution Symfony qui a donné lieu à la réponse HTTP en question/
Examinez la page du « Profiler Symfony » qui s’affiche.
Figure 2 : Page du « Symfony Profiler » dans les outils du développeur Web
Identifiez les informations de mise-au-point utiles, expliquant le contexte détaillé de la requête HTTP en question.
2.3. TODO Étape 1-c : Accès réussi à une ressource de l’application ToDo
Examiner le comportement de l’application Symfony visible dans les outils du développeur Symfony, quand une requête HTTP est réussie.
Naviguez sur l’URL
http://localhost:8000/todo/
Une page d’accueil sommaire de l’application s’affiche. Quel est le code de réponse de la réponse HTTP ?
Vérifiez ce code aussi bien :
- dans les traces du serveur sur sa sortie standard dans le terminal,
- que dans la barre d’outils de Symfony affichée en bas de page.
Cliquez sur la case du code de retour « 200 » en bas à gauche de la barre d’outils Symfony
Constatez les informations affichées dans la page « Request / Response » qui s’affiche, comme :
- le lien «
TodoController::indexAction
» - nom du point d’entrée Symfony exécuté en réponse à la requête
- les « Request Headers »
- les en-têtes de la requête envoyés par
le navigateur comme
host
, que vous connaissez - le paramètre
DATABASE_URL
dans les « Server Parameters / Defined in .env » - la variable de connexion à la base de données que vous connaissez aussi
- …
- le lien «
Cliquez sur le menu « Routing » à gauche
Remarquez le nom de la « route » correspondant à cette requête :
home
et la correspondance avec le chemin d’URL/todo/
.L’application Symfony maintient une table de routage des chemins d’accès aux ressources, et des codes PHP gestionnaires.
Ici, la requête est réussie (code de retour
200
) car on est sur une route connue.Le code du contrôleur Symfony gérant cette route qui a été invoqué est dans la méthode
App\Controller\TodoController::indexAction()
, que nous verrons plus loin, dans le code PHP.Essayez de naviguer cette fois sur l’URL
http://localhost:8000/hello
Examinez le code de retour et les informations de routage affichées. Est-ce cohérent ?
2.4. TODO Étape 1-d : Examen de la table de routage de ToDo
On va examiner le mécanisme de la table de routage qui permet de définir quel composant de l’application Symfony écrit par le développeur doit être exécuté en réponse aux requêtes HTTP.
Dans la séance précedente, on avait vu que le code de l’application
pouvait être exécuté au moyen des classes de son interface en mode
« ligne de commande », gérant des sous-commandes app:...
de symfony console
, pour
afficher des informations sur la sortie standard, par exemple.
Par exemple, la commande symfony console app:list-todos
invoquait
l’exécution de la méthode App\Command\ListTodosCommand::execute
présente dans le fichier PHP src/Command/ListTodosCommand.php
.
Ici, en environnement Web, le code de l’application est exécuté en réponse aux requêtes HTTP, via l’invocation par PHP du moteur du noyau Symfony. Symfony appelle une méthode de classe Contrôleur en fonction de sa table de routage.
Examinez la table de routage Web de l’application ToDo
:
symfony console debug:router
--------------------------- -------- -------- ------ ----------------------------------- Name Method Scheme Host Path --------------------------- -------- -------- ------ ----------------------------------- _preview_error ANY ANY ANY /_error/{code}.{_format} _wdt ANY ANY ANY /_wdt/{token} _profiler_home ANY ANY ANY /_profiler/ _profiler_search ANY ANY ANY /_profiler/search _profiler_search_bar ANY ANY ANY /_profiler/search_bar _profiler_phpinfo ANY ANY ANY /_profiler/phpinfo _profiler_xdebug ANY ANY ANY /_profiler/xdebug _profiler_font ANY ANY ANY /_profiler/font/{fontName}.woff2 _profiler_search_results ANY ANY ANY /_profiler/{token}/search/results _profiler_open_file ANY ANY ANY /_profiler/open _profiler ANY ANY ANY /_profiler/{token} _profiler_router ANY ANY ANY /_profiler/{token}/router _profiler_exception ANY ANY ANY /_profiler/{token}/exception _profiler_exception_css ANY ANY ANY /_profiler/{token}/exception.css app_admin_dashboard_index ANY ANY ANY /admin home GET ANY ANY /todo/ todo_list GET ANY ANY /todo/list todo_index GET ANY ANY /todo/index todo_show GET ANY ANY /todo/{id} --------------------------- -------- -------- ------ -----------------------------------
Ainsi, l’accès par le client HTTP à l’URL
http://localhost:8000/todo/
entraîne le traitement de la requête
HTTP GET
(correspondant à « Method » valant GET
) sur la ressource /todo/
(« Path » valant /todo
), qui peut donc être routée vers la route nommée home
.
Si on demande plus de détails dans cette commande, avec symfony
console debug:router --show-controllers
la colonne « Controller » nous
affiche, en face de cette route home
le nom de la méthode qui sera
appelée par le routeur Symfony : App\Controller\TodoController::indexAction()
.
On va voir que cette méthode est celle d’une classe Contrôleur Symfony
(codée dans le fichier src/Controller/TodoController.php
).
3. TODO Étape 2 : Examen du code du contrôleur HTTP de ToDo
On va maintenant examiner la façon dont le programmeur peut configurer les informations de routage et programmer le code PHP exécuté en réponse aux requêtes HTTP.
Ouvrez le code du contrôleur Web Symfony
src/Controller/TodoController.php
dans l’IDE.Note : vous pouvez également consulter son code depuis le profileur Symfony en cliquant sur le lien «
TodoController::indexAction
» dans la page du menu « Request / Response ».Observez les annotations
Route
présentes dans le code, à l’aide d’attributs PHP 8 :... use Symfony\Component\Routing\Annotation\Route; ... #[Route('/todo')] class TodoController extends AbstractController { ...
ceci définit un préfixe qui s’appliquera à l’ensemble des routes des méthodes de toute la classe.
puis :
#[Route('/', name: 'home', methods: ['GET'])] public function indexAction() {
ainsi,
indexAction()
est associé au chemin de route'/todo'
+ ’/
’ : ’/todo/
’, et au nom de routehome
.Vous retrouvez les informations présentes pour le chemin (« Path »), dans la table de routage.
Examinez le code de la méthode
TodoController::indexAction()
Le code est relativement simple :
... use Symfony\Component\HttpFoundation\Response; ... $htmlpage = '<!DOCTYPE html><html>....</html>'; return new Response( $htmlpage, Response::HTTP_OK, array('content-type' => 'text/html') );
- définition d’un contenu HTML à renvoyer en réponse à la requête
- construction d’une réponse HTTP avec les propriétés suivantes :
- contenu de la réponse (HTML)
- code de réponse HTTP
OK
(en fait une constanteResponse::HTTP_OK
qui vaut 200) - une liste d’en-têtes de réponse : ici la définition explicite du type HTML pour le contenu renvoyé (
Content-type
)
Vous retrouvez les composants essentiels d’une réponse HTTP : code de réponse, en-têtes et contenu.
Ce code est très simple, et n’est pas représentatif de ce qu’on
effectue d’ordinaire dans un contrôleur d’application Symfony, mais
nous l’avons construit pour les vertus de l’exemple. Ce n’est pas
hyper élégant, mais assez explicite… et ça marche.
Nous n’avons pas encore étudié le langage HTML, donc il se peut que
le contenu de la réponse ne vous semble pas trivial à ce
stage. Nous l’étudierons plus en détail dans une prochaine séance
(et verrons comment générer du code HTML plus proprement, avec les gabarits).
3.1. TODO Test des routes existantes
Vérifiez que les routes listées ci-dessus sont bien accessibles à partir d’un navigateur :
- Liste des tâches :
http://localhost:8000/todo/list
- Affichage d’une tâche :
http://localhost:8000/todo/1
- …
Comparez la sortie de la commande debug:route
, testez les URL
correspondantes et consultez le code du contrôleur Web.
Les routes commençant par un underscore, comme _profiler
sont des
routes spéciales liées au fonctionnement des outils de développement
de Symfony, comme le Profiler qu’on a utilisé un peu plus tôt. Elles
n’existent qu’en environnement de développement, indépendamment du
code de notre application présent dans src/Controller/
.
Vous comprenez maintenant comment est déclaré dans le code de la partie Routage de la gestion des requêtes HTTP dans une application Symfony.
4. Étape 3 : Ajout d’un Contrôleur Web, dans Todo, pour les étiquettes
Le but de cette étape est d’ajouter un contrôleur Web dans l’application Todo
On peut écrire du code d’une classe PHP dans src/Controller/
ou bien
utiliser un assistant générateur de code de
Symfony : make:controller
. Il génère pour nous une nouvellle classe
Contrôleur, et les éléments associés.
4.1. Étape 3-a : Ajout d’une classe TagController
Vous allez utiliser l’assistant générateur de code make:controller
pour ajouter de quoi consulter les étiquettes (Tag
) dans l’application
Todo.
On adaptera ensuite le code généré, sur le modèle de la
classe TodoController
.
Procédez aux étapes suivantes :
utilisez l’assistant
make:controller
pour générer le code d’une classeTagController
:symfony console make:controller TagController
created: src/Controller/TagController.php created: templates/tag/index.html.twig Success! Next: Open your new controller class and add some pages!
allons-y, et ouvrons le fichier source généré
src/Controller/TagController.php
dans l’IDE.Rechargez le contenu affiché dans le panneau d’arborescence des fichiers : on a généré de nouveaux fichiers, mais l’IDE ne s’en est probablement pas rendu compte.
Vous constatez que le code est plutôt concis.
L’assistant a généré également un fichier de gabarit Twig :
templates/tag/index.html.twig
, qui est utilisé, dans ce code, pour générer le contenu d’une page Web.Vous étudierez prochainement les gabarits Twig, donc on ne va pas aller voir le détail de ce gabarit pour l’instant.
consultez la table de routage de l’application :
symfony console debug:router
Elle contient maintenant la nouvelle route
app_tag
accessible sur/tag
, ce qui est conforme à la déclaration des attributs de la méthodeindex()
dans le code du contrôleur (#[Route('/tag', name: 'app_tag')]
).lancez le serveur Web :
symfony server:start
Testez l’URL
http://localhost:8000/tag
Vous obtenez sans surprise la page « Hello TagController! » dont le contenu est spécifiée par le gabarit
templates/tag/index.html.twig
.
4.2. Étape 3-b : Utilisation de dump()
en contexte Web
Modifiez le code de la méthode
TagController::index()
pour ajouter un appel àdump()
:#[Route('/tag', name: 'app_tag')] public function index(): Response { dump("hello world"); return $this->render('tag/index.html.twig', [ 'controller_name' => 'TagController', ]); }
sans avoir besoin de relancer le serveur Web, rechargez juste la page
/tag
affichée dans le navigateur.Vous devez voir apparaître dans la barre d’outils Symfony en bas de page, une icône « cible » qui donne accès à l’affichage des dumps (il suffit de passer la souris dessus pour voir les messages en pop-ups).
Figure 3 : Affichage d’un pop-up pour les valeurs des dump()
L’utilisation de dump()
est très utile pour la mise-au-point quand on
teste en mode Web.
Cela permet de mettre des affichages d’infos pour déboguer un peu partout dans le code, sans polluer l’affichage des pages, puisque les infos de dump sont cachées dans ce sous-menu de la barre d’outils Symfony.
On peut maintenant passer au codage des traîtements à effectuer pour afficher une liste d’étiquettes.
4.3. Étape 3-c : Ajout de l’affichage des étiquettes
Nous pouvons maintenant ajouter une méthode destinée à charger et afficher toutes les étiquettes.
Le chargement se fera depuis la base de données avec Doctrine, comme pour ce qu’on sait déjà faire dans l’exécution des commandes en mode console.
Ajoutez la méthode suivante :
use App\Repository\TagRepository; // ... /** * Lists all tags entities. */ #[Route('/tag/list', name: 'tag_list', methods: ['GET'])] public function listAction(TagRepository $tagRepository) { $htmlpage = '<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>tags list!</title> </head> <body> <h1>tags list</h1> <p>Here are all your tags:</p> <ul>'; $tags = $tagRepository->findAll(); foreach($tags as $tag) { $htmlpage .= '<li>'. $tag->getName() .'</li>'; } $htmlpage .= '</ul>'; $htmlpage .= '</body></html>'; return new Response( $htmlpage, Response::HTTP_OK, array('content-type' => 'text/html') ); }
La génération du HTML est inspirée de ce qui est fait dans
TodoController::listAction()
(on verra plus tard comment faire mieux avec des gabarits).Quand à la connexion avec la base de données, on diffère un peu du code de
TodoController
: on utilise ici le mécanisme de « cablage » automatique (autowiring) des contrôleurs avec les repositories de Doctrine.Ce mécanisme est présenté dans le deuxième exemple de la documentation Fetching Objects from the Database :
Another possibility is to use the ProductRepository using Symfony’s autowiring and injected by the dependency injection container.
le conteneur d’injection de dépendance dont il est question ici, c’est le mécanisme qui permet de passer un repository (
TagRepository $tagRepository
) en argument de notre méthodelistAction()
.Testez sur l’URL
/tag/list
que cela affiche bien les tâches présentes dans la base de données.Cliquez sur l’icône représentant un « cylindre » à 3 couches en bas de page dans la barre d’outils du développeur Symfony.
Vous aboutissez à la page « Doctrine » des outils de mise au point, qui permet de voir la requête
SELECT
qui a été générée par Doctrine lors de l’appel àfindAll()
.
Voilà pour la création d’un contrôleur sur l’application Todo. Vous pouvez maintenant passer à l’ajout de contrôleurs dans votre projet.
5. TODO Étape 4 : Ajout d’un Contrôleur Web dans le projet
Vous allez maintenant pouvoir démarrer l’ajout d’un contrôleur Web dans votre projet
Vous commencez maintenant cette mise en œuvre, en vous référant au Guide de réalisation du projet.
Les instructions sont données dans la section « Création des premières pages publiques, en consultation » pourvu que vous ayez suffisamment avancé sur les précédentes tâches du projet.
Vous la continuerez en travail hors présentiel sur votre projet, d’ici la prochaine séance de TP (Notez le label « Après_TP_4 » dans la section).
6. Évaluation
À la fin de cette séquence, vous savez :
- utiliser des outils de la barre d’outils Symfony pour examiner le fonctionnement de l’application côté serveur
- identifier comment le code PHP est appelé en réponse aux requêtes HTTP dans une application Web Symfony, via les contrôleurs
- examiner la table de routage d’une application Symfony
- générer le code d’une classe contrôleur avec
make:controller
- afficher des informations de déboguage avec
dump()
- cabler automatiquement un contrôleur avec Doctrine pour permettre l’exécution de requêtes en base de données
- examiner les requêtes SQL exécutées sous le capot
7. TODO Ensuite, d’ici la semaine prochaine
D’ici le prochain cours magistral, vous allez travailler en hors-présentiel, sur l’apprentissage de HTML et Twig, pour la vous initier à la fabrication des pages HTML.
Vous vous appuierez sur le support de travail hors-présentiel 4-5 pour cela.