TD5 – Architecture MVC avancée 1/2 Contrôleur frontal, échappement du HTML, vues modulaires, CRUD
Nous allons continuer de développer notre site-école de covoiturage. Au fur et à mesure que le projet grandit, nous allons bénéficier du patron d’architecture MVC qui va nous faciliter la tâche.
Le but des TDs 5 & 6 est donc d’avoir un site qui propose une gestion minimale des utilisateurs et des trajets proposés en covoiturage. En attendant de pouvoir gérer les sessions d’utilisateur, nous allons développer l’interface “administrateur” du site.
Remise en route
Lors du TD4, nous avons commencé à utiliser l’architecture MVC. Le code était découpé en trois parties :
-
Le modèle (e.g.
Modele/ModeleUtilisateur.php) est une bibliothèque des fonctions permettant de gérer les données, i.e. l’interaction avec la base de données dans notre cas. Cette bibliothèque sera utilisée par le contrôleur. -
Les vues (e.g.
vue/utilisateur/liste.php) ne doivent contenir que les parties du code qui écrivent la page Web. Ces scripts seront appelés par le contrôleur qui s’en servira comme d’un outil pour générer la page Web ; -
Le contrôleur est la partie principale du script PHP. Dans notre cas, il est composé de deux parties :
-
le routeur (e.g.
Controleur/routeur.php) est la page que l’utilisateur demande pour se connecter au site. C’est donc le script PHP de cette page qui est exécuté. Cette page est chargée de récupérer l’action envoyée avec la demande de la page et d’appeler le bon code du contrôleur correspondant. -
la partie
Utilisateurdu contrôleur (e.g.Controleur/ControleurUtilisateur.php) contient le code source des actions. C’est donc ici qu’est présente la logique du site Web : on y appelle le modèle pour récupérer/enregistrer des données, on traite ces données, on appelle les vues pour écrire la page Web…
-
Réorganisation du site
Limitation des pages accessibles
L’organisation actuelle du site pose un problème majeur : un client du site Web
est censé accéder au site avec une requête Controleur/routeur.php. Mais rien
ne garantit qu’il n’essayera pas d’accéder aux autres fichiers PHP “internes”.
Nous allons donc séparer les fichiers PHP dans des dossiers différents en
fonction de s’ils doivent être accessibles sur le Web.
-
Copiez/collez dans un nouveau dossier
TD5tous les fichiers du dossierTD4. -
Renommez et déplacez le fichier
Controleur/routeur.phppour qu’il devienneweb/controleurFrontal.phpen évitant d’utiliser PhpStorm. En effet, PhpStorm vous rajouterait des lignesnamespace ...etuse ...en haut de vos scripts PHP qu’il faudrait supprimer.Note : Ce script s’appelle contrôleur frontal (front controller en anglais) puisque c’est la partie visible de notre site.
-
Déplacez les dossiers
Configuration,Controleur,Modeleetvuedans un dossiersrcen évitant d’utiliser PhpStorm.Ce déplacement casse quand même le site Web, mais nous allons le réparer dans le prochain exercice.
Vous avez donc la structure de fichiers suivante :

Réparer les inclusions de fichiers du site
Lorsque l’on a déplacé la page d’accueil vers controleurFrontal.php, tous nos chemins relatifs de fichiers ont été décalés. En effet, comme tous les fichiers PHP
sont exécutés dans controleurFrontal.php, les chemins relatifs de fichiers sont interprétés par rapport au dossier du contrôleur frontal. Ce problème se produit dans les require, require_once et parse_ini_file.
Prenons l’exemple du parse_ini_file de ../Configuration/ConfigurationBaseDeDonnees.ini dans ConnexionBaseDeDonnees.php :
- Dans le TD4, cette adresse était relative à
/chemin_du_site/Controleur/routeur.php, donc elle pointait vers
/chemin_du_site/Controleur/../Configuration/ConfigurationBaseDeDonnees.ini, donc sur
/chemin_du_site/Configuration/ConfigurationBaseDeDonnees.ini - Désormais, cette adresse est relative à
/chemin_du_site/web/controleurFrontal.php. Elle va renvoyer vers l’adresse inconnue
/chemin_du_site/web/../Configuration/ConfigurationBaseDeDonnees.ini, c.-à-d.
/chemin_du_site/Configuration/ConfigurationBaseDeDonnees.ini. Or la bonne adresse est
/chemin_du_site/src/Configuration/ConfigurationBaseDeDonnees.ini.
Pour éviter ce comportement qui porte à confusion, nous allons utiliser des chemins
de fichiers absolus. Pour ce faire, nous utiliserons la constante __DIR__ qui contient le chemin absolu du dossier contenant le fichier actuel. Par exemple, nous pouvons écrire dans ConnexionBaseDeDonnees.php
// __DIR__ renvoie vers le dossier contenant ConnexionBaseDeDonnees.php
// c-à-d ici __DIR__ égal "/chemin_du_site/src/Modele"
$configurationBaseDeDonnees = parse_ini_file(
__DIR__ . '/../Configuration/ConfigurationBaseDeDonnees.ini',
false,
INI_SCANNER_RAW
);
// On obtient "/chemin_du_site/src/Modele/../Configuration/ConfigurationBaseDeDonnees.ini"
// c-à-d "/chemin_du_site/src/Configuration/ConfigurationBaseDeDonnees.ini"
À partir de maintenant, nous n’utiliserons plus de chemins relatifs dans require, require_once et parse_ini_file. Il va donc falloir changer ceux qui existent déjà.
- Changez le
parse_ini_filedansConnexionBaseDeDonnees.phppour qu’il utilise un chemin absolu ; - Changez tous les
require_oncequi chargent des classes ; - Changez le
requiredansControleurUtilisateur::afficherVuequi charge les vues ; - Si besoin, changez les liens de
liste.phpet l’attributactiondu formulaireformulaireCreation.phppour qu’ils renvoient surcontroleurFrontal.phpau lieu derouteur.php.
Maintenant que le site remarche et que les scripts accessibles sur le Web sont isolés dans des dossiers différents, nous allons pouvoir appliquer la restriction d’accès.
-
Nous allons indiquer au serveur Web Apache que les fichiers ne sont pas accessibles sur internet par défaut. Pour ceci, créez un fichier
.htaccessà la racine de votre siteTD5avec le contenu suivant :Require all denied -
Pour indiquer que les fichiers du dossier
websont accessibles, créez un fichierweb/.htaccessavec le contenu suivant :Require all granted -
Vérifiez que l’accès par internet aux scripts autres que
web/controleurFrontal.phpaffiche une page WebForbidden You don't have permission to access this resource.
Chargement automatique des classes
Nous venons de faire l’expérience des limites des chemins relatifs. Dans le
monde professionnel du PHP, on utilise le chargement automatique de classe
(autoloading en anglais) : quand PHP doit utiliser une classe qu’il ne connait
pas, il va charger le fichier de déclaration de cette classe.
Vous avez déjà utilisé ce mécanisme en Java sans le savoir. En effet, vous
n’avez jamais inclus de fichier de déclaration de classe en Java avec des
require_once comme en PHP. Alors, comment fait Java pour savoir quel fichier
inclure ?
Le chemin du fichier est directement lié au nom de classe qualifié, c.-à-d. du
nom de classe précédé du nom du package. Par exemple, le fichier Java
src/main/java/fr/umontpellier/iut/svg/SVG.java
package fr.umontpellier.iut.svg;
public class SVG { }
contient la déclaration de la classe dont le nom qualifié est
fr.umontpellier.iut.svg.SVG. On imagine bien comment Java s’est servi du nom de
classe qualifié pour trouver l’adresse du fichier de déclaration.
Les principaux avantages du chargement automatique de classe sont :
- le chargement de classe devient paresseux, c.-à-d. qu’une classe ne sera chargée que quand on a besoin d’elle. Pour de gros sites Web, cette économie est substantielle.
- Ce mécanisme sera indispensable pour pouvoir utiliser des bibliothèques
externes PHP avec
composer. Les élèves du parcours A le verront lors du semestre 4, et ceux du parcours D au semestre 5. - On évite les problèmes de chemins relatifs.
- On évite l’erreur de charger deux fois une classe (que l’on traitait avec
require_onceavant). - La solution proposée sera portable, c.-à-d. qu’elle gèrera les sordides subtilités entre les chemins de fichier Windows et ceux de Linux / Mac.
Espaces de noms
Avant d’utiliser le chargement automatique, nous avons besoin de préciser nos
noms de classes avec des espaces de noms (namespace en anglais). C’est
l’équivalent des package en Java.
- Rajoutez
namespace App\Covoiturage\Modele;au début de
src/Modele/ConnexionBaseDeDonnees.php.Explication : La déclaration
namespaceregroupe toutes les classes (et fonctions) déclarées dans le fichier dans l’espace de nomApp\Covoiturage\Modele, ce qui a pour effet de rajouter un préfixe à leur nom. Ainsi, la classe déclarée dansConnexionBaseDeDonnees.phps’appelle maintenantApp\Covoiturage\Modele\ConnexionBaseDeDonnees.Attention : Les espaces de nom utilisent des antislashs
\, tandis que les chemins de fichiers Linux/Mac utilisent des slashs/. -
Le site est de nouveau cassé :
ModeleUtilisateur.phpne connaît pas la classeConnexionBaseDeDonnees. En effet, cette classe s’appelle désormaisApp\Covoiturage\Modele\ConnexionBaseDeDonnees.
Complétez le nom de la classeConnexionBaseDeDonneesdansModeleUtilisateur.php.Note :
- Vous ne devez pas toucher aux noms de fichiers dans les
require_once, mais plutôt changer le nom de classeConnexionBaseDeDonneesdans les appels à des méthodes statiques. - Utilisez la recherche/remplacement de PhpStorm avec
Ctrl+R.
- Vous ne devez pas toucher aux noms de fichiers dans les
-
Le site est toujours cassé : La classe
PDOdansConnexionBaseDeDonnees.phpest comprise commeApp\Covoiturage\Modele\PDOà cause dunamespace App\Covoiturage\Modele. Or son nom complet est\PDO.
Spécifiez quePDOest dans l’espace de nom global en appelant la classe\PDO.La même remarque tient pour toutes les autres classes de la librairie standard de PHP (comme
DateTimeque nous avions utilisée dansTrajetdans un précédent TD, par exemple). -
Vérifiez que le site remarche.
-
Vous conviendrez volontiers que ce nom de classe à rallonge est pénible. Nous allons utiliser un alias à la place :
// ConnexionBaseDeDonnees est un raccourci pour App\Covoiturage\Modele\ConnexionBaseDeDonnees use App\Covoiturage\Modele\ConnexionBaseDeDonnees as ConnexionBaseDeDonnees; // PDO est un raccourci pour \PDO use \PDO as PDO; // ou syntaxe équivalente plus rapide use App\Covoiturage\Modele\ConnexionBaseDeDonnees; use \PDO;Raccourcissez les noms de classe de
ConnexionBaseDeDonnees,PDO(et éventuellementPDOException) dansModeleUtilisateur.phpgrâce à cet alias (à placer au début du fichier).Remarques :
useest similaire àimporten Java.- Si une classe utilise une autre classe et si ces deux classes se trouvent
dans le même
namespace, il n’y a pas besoin de faire d’import explicite avecuse, ce qui est notre cas avecConnexionBaseDeDonneesdansModeleUtilisateur. - PhpStorm peut faire ce travail à votre place. Par exemple, quand il ne
connaît pas la classe
Configuration, il la surligne pour indiquer un warning. Lorsque votre curseur est sur la ligne du warning, une ampoule apparaît pour vous proposer des solutions rapides (ou faitesAlt+Entrée). Choisissez la solution Import Class.
-
Vérifiez que le site marche toujours.
-
Supprimez le
require_oncequi charge et exécute le fichierConnexionBaseDeDonnees.phpdansModeleUtilisateur.php.Le site est de nouveau cassé : l’application ne sait pas où chercher la classe pointée par le
use(et la charger). Nous allons régler cela dans le prochain exercice.
PSR-4 : Autoloading Standard
Le groupe PHP-FIG (PHP Framework Interoperability Group) pour l’interopérabilité de PHP travaille pour standardiser la pratique de PHP. Ce travail vise notamment à ce que les différents composants ou framework PHP puissent bien communiquer entre eux.
Parmi les recommandations de standards PHP (PSR en anglais) les plus importants, on trouve :
PhpStorm peut formater votre code en suivant les standards de style PSR-1 et
PSR-12 en allant dans le menu Code > Reformat Code (ou en tapant
Ctrl+Alt+L).
Dans la suite, nous allons vous fournir une classe Psr4AutoloaderClass qui
implémente un chargeur automatique de classe suivant le standard PSR-4.
En pratique, après avoir initialisé la classe avec
$chargeurDeClasse = new App\Covoiturage\Lib\Psr4AutoloaderClass();
$chargeurDeClasse->register();
vous pourrez enregistrer une association entre un espace de nom et un dossier
$chargeurDeClasse->addNamespace('App\Covoiturage', __DIR__ . '/../src');
Vous pouvez maintenant utiliser n’importe quelle classe dont l’espace de noms
commence par App\Covoiturage et Psr4AutoloaderClass chargera le fichier de
déclaration de classe correspondant avec un require_once. Par exemple, si vous
exécutez maintenant dans ModeleUtilisateur.php
use App\Covoiturage\Modele\ConnexionBaseDeDonnees;
$pdo = ConnexionBaseDeDonnees::getPdo();
alors Psr4AutoloaderClass exécutera pour vous
require_once(__DIR__ . '/../src/Modele/ConnexionBaseDeDonnees.php')
Le chemin de fichier est déterminé par Psr4AutoloaderClass en utilisant
l’association déclarée précédemment avec addNamespace pour remplacer
'App\Covoiturage' par __DIR__ . '/../src' dans le nom de classe qualifié de
ConnexionBaseDeDonnees.
-
Créez le dossier
src/Lib(attention à la majuscule). Enregistrez le fichier Psr4AutoloaderClass.php directement à l’emplacementsrc/Lib/Psr4AutoloaderClass.php.Attention : Un bug apparaît si vous vous servez de PhpStorm pour déplacer
Psr4AutoloaderClasset le changer de dossier. Il est donc important d’enregistrerPsr4AutoloaderClassdirectement dans le bon dossier. -
Au tout début du contrôleur frontal, incluez ce fichier à l’aide d’un
require_once. Utilisez un chemin de fichier absolu avec__DIR__comme vu précédemment. - Ajoutez le code suivant dans le contrôleur frontal juste avant de traiter
les actions :
// initialisation en activant l'affichage de débogage $chargeurDeClasse = new App\Covoiturage\Lib\Psr4AutoloaderClass(true); $chargeurDeClasse->register(); // enregistrement d'une association "espace de nom" → "dossier" $chargeurDeClasse->addNamespace('App\Covoiturage', __DIR__ . '/../src');En résumé, ce code dit au système d’autoloading de PHP que les classes dont l’espace de nom commence par
App\Covoituragese trouvent dans le dossiersrc. - Vérifiez que le site fonctionne de nouveau.
Un affichage est apparu en haut de votre page. C’est le debug de Psr4AutoloaderClass qui vous indique les classes qu’il a chargé. Avec les changements effectués dans l’exercice précédent, la classe App\Covoiturage\Modele\ConnexionBaseDeDonnees est chargée automatiquement en incluant le fichier src/Modele/ConnexionBaseDeDonnees.php dans ModeleUtilisateur.
Cet affichage de débogage est là pour vous aider à comprendre le fonctionnement de l’autoloader. Vous pourrez le désactiver dans un prochain exercice.
- Répétez le processus de l’exercice précédent afin d’enlever tous les
require_oncede fichier de déclaration de classe (sauf pourPsr4AutoloaderClassdanscontroleurFrontal.php) :- ajout de
namespacedans chaque classe, - utilisation d’alias pour faire référence à cette classe,
- suppression des
require_once(utilisation d’unuseà la place).
Nous vous conseillons de procéder classe par classe, dans l’ordre suivant :
ModeleUtilisateur,- puis
ControleurUtilisateur, - puis
controleurFrontal.php(pour la classeControleurUtilisateur, pas pourPsr4AutoloaderClass).
Nous n’enlèverons pas le
requirede la fonctionafficherVuedu contrôleur, car nous l’utilisons pour charger un script (et pas une classe) de manière dynamique (le nom du script à charger est passé en paramètre).Remarque : Il n’y a pas besoin d’utiliser
use App\Covoiturage\Modele\ConnexionBaseDeDonnees;dans la classeModeleUtilisateurcar ces classes se trouvent dans le mêmenamespace App\Covoiturage\Modele. - ajout de
-
Le site doit maintenant fonctionner à nouveau.
- Maintenant que vous avez compris le principe de
Psr4AutoloaderClass, vous pouvez désactiver son affichage de débogage danscontroleurFrontal.php:$chargeurDeClasse = new App\Covoiturage\Lib\Psr4AutoloaderClass(false);
Sécurité des vues
Nous allons apprendre pourquoi nous devons faire attention lorsque nous remplaçons une variable PHP par sa valeur dans l’écriture de la page HTML. Vous allez voir que les raisons sont assez similaires au problème derrière les injections SQL.
Prenons l’exemple de notre vue detail.php qui écrit entre autres
echo "<p> Utilisateur {$u->getLogin()} </p>";
Que se passe-t-il si l’utilisateur a rentré du code HTML à la place d’un login ?
Créez un utilisateur de login <h1>Hack et regardez comment elle
s’affiche. Inspectez le code source HTML correspondant pour comprendre ce qu’il
s’est passé.
La valeur du login est interprétée comme du code HTML. Ce comportement est indésirable et peut carrément être dangereux, notamment si l’utilisateur se met à écrire du JavaScript.
Échappement dans du HTML
Pour éviter cela, il faut faire attention aux caractères protégés du HTML. Voici la liste des caractères qui font la différence entre du texte pur et du code HTML :
- les chevrons
<et>car ils délimitent les balises HTML ; - les guillemets simples
'ou doubles"car ils délimitent les valeurs des attributs ; - L’esperluette
&car elle sert à échapper les caractères. Par exemple, le code HTML&sert à afficher une esperluette&.
Ces caractères spéciaux doivent être échappés dans les vues pour que le texte s’affiche bien mais ne risque pas de changer la structure du document HTML. Voici comment échapper ces caractères :
< |
> |
& |
" |
' |
< |
> |
& |
" |
' |
Bonne nouvelle : PHP fait ceci pour nous avec la fonction
htmlspecialchars. Par
exemple, le code
echo htmlspecialchars('<a href="test">Test</a>');
renvoie
<a href="test">
Le remplacement des caractères spéciaux a bien eu lieu.
Du coup, il faut utiliser htmlspecialchars à chaque fois que l’on écrit une
variable non sûre (par ex. provenant de l’utilisateur) comme texte de la page
HTML ou comme attribut d’une balise.
$nom = "<h1>Danger ! </h1>";
echo "Page personnelle de ". $nom; // Danger !
echo "Page personnelle de ". htmlspecialchars($nom); // Écriture sécurisée
$valeurDefaut = '"><script>alert("Danger!");</script>';
echo '<input type="text" value="' . $valeurDefaut . '">'; // Danger !
echo '<input type="text" value="' . htmlspecialchars($valeurDefaut) . '">'; // Écriture sécurisée
-
Changer donc toutes vos vues pour appliquer la fonction
htmlspecialcharsà toutes les variables PHP qui se trouvent à un endroit où du code HTML pourrait être interprété. L’endroit typique est dans les zones de texte.Nous vous conseillons de créer des variables temporaires pour stocker le texte échappé, par exemple
$loginHTML, puis d’afficher ces variables.Ne changez pas les variables PHP qui sont utilisées pour construire des liens ou des URLs, nous allons les traiter dans le prochain exercice.
-
Vérifiez que votre utilisateur de login
<h1>Hacks’affiche maintenant correctement et ne crée plus de balise HTML<h1>dans les vues de liste et de détail. Allez voir dans le code source comment le login a été échappé.
Échappement des URLs
De la même manière, il faut encoder les valeurs dans les query strings des URLs pour éviter d’en changer le sens
lorsque l’on insère une donnée fournie par l’utilisateur. Par exemple, nous
allons devoir échapper les caractères ? et = puisqu’ils permettent de passer
de l’information dans l’URL avec le format query string.
Pour information, la liste des caractères réservés des URLs est
:/?#[]@!$&'()*+,;=. Nous allons donc utiliser la fonction
rawurlencode pour
échapper les variables PHP qui interviennent dans des query string.
-
Créez un utilisateur de login
&a=ben utilisant votre actionafficherFormulaireCreation; -
Observez que le lien vers la vue de détail de cet utilisateur ne marche pas. Pourquoi ?
-
Changer la vue
liste.phppour qu’elle encode à l’aide derawurlencodela variable PHP correspondant au login.
Attention : Il ne faut pas encoder le login déjà échappé pour le HTML. Il faut créer deux variables : un login$loginHTMLpour le HTML et un$loginURLpour les URLs. -
Testez que le lien vers la vue de détail remarche.
Source : RFC 3986 sur les URI
Vues modulaires
En l’état, certains bouts de code de nos vues se retrouvent dupliqués à de multiples endroits. Les prochaines questions vont vous aider à réorganiser le code pour éviter les redondances en vue d’améliorer la maintenance du code et son débogage.
Mise en commun de l’en-tête et du pied de page
Actuellement, les scripts de vues sont chargés d’écrire l’ensemble de la page
Web, du
<!DOCTYPE HTML><html>...
jusqu’au
</body></html>
. C’est problématique car cela nous empêche de mettre facilement deux vues bout à
bout. Voyons cela sur un exemple.
Supposez que l’on souhaite que notre vue de création (action
creerDepuisFormulaire) d’utilisateur affiche “Votre utilisateur a bien été
créé” puis la liste des utilisateurs. Il serait donc naturel d’écrire le
message puis d’appeler la vue liste.php. Mais comme cette dernière vue
écrivait la page HTML du début à la fin, on ne pouvait rien y rajouter au milieu
!
Décomposons nos pages Web en trois parties : le header (en-tête), le body (corps ou fil d’Ariane) et le footer (pied de page). Dans le site final de l’an dernier, on voit bien la distinction entre les 3 parties. On note aussi que le header et le footer sont communs à toutes nos pages.
Au niveau du HTML, l’en-tête de la page (header) correspond à la partie :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Liste des trajets</title>
</head>
<body>
<header>
<nav>
<!-- Le menu de l'en-tête -->
</nav>
</header>
le corps de la page (body) à la partie :
<main>
<h1>Liste des trajets:</h1>
<ol>
<li>...</li>
<li>...</li>
</ol>
</main>
et le pied de page (footer) à la partie :
<footer>
<p>Copyleft Romain Lebreton</p>
</footer>
</body>
</html>
Nous allons donc changer nos vues pour qu’elles n’écrivent plus que le corps de la page. Enfin une vue spéciale, appelée vue générique, chargera l’une de ces vues “corps” en l’incluant dans l’en-tête et le pied de page communs.
-
Créer une vue générique
TD5/vue/vueGenerale.phpavec le code suivant. La fonction devueGenerale.phpest de charger un en-tête et un pied de page communs, ainsi que la vue dont le nom de fichier est stocké dans la variable$cheminCorpsVue(et le titre de page contenu dans$titre).<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <title><?php echo $titre; ?></title> </head> <body> <header> <nav> <!-- Votre menu de navigation ici --> </nav> </header> <main> <?php require __DIR__ . "/{$cheminCorpsVue}"; ?> </main> <footer> </footer> </body> </html>Rappel : L’IDE devrait signaler une erreur/warning indiquant que les variables
$titreet$cheminCorpsVuesont non définies. Pensez à ajouter une documentation en format PHPDoc avant l’utilisation de la variable pour avoir un code propre.Par exemple, pour
$titre:/** * @var string $titre */ -
Dans vos vues existantes, supprimer les parties du code sauf ce qui rentrera dans le corps de la page
<main>. -
Reprendre l’action
afficherListedu contrôleur pour afficher la vuevueGenerale.phpavec les paramètres supplémentaires"titre" => "Liste des utilisateurs","cheminCorpsVue" => "utilisateur/liste.php". -
Testez votre action
afficherListe. Regardez le code source de la page Web pour vérifier que le HTML généré est correct. -
Modifiez les autres actions et testez votre site.
Nous allons bénéficier de notre changement d’organisation pour rajouter un header et un footer (minimalistes) à toutes nos pages.
-
Modifier la vue
vueGenerale.phppour ajouter en en-tête de page une barre de menu, avec deux liens vers les différents contrôleurs :<nav> <ul> <li> <a href="controleurFrontal.php?action=afficherListe&controleur=utilisateur">Gestion des utilisateurs</a> </li><li> <a href="controleurFrontal.php?action=afficherListe&controleur=trajet">Gestion des trajets</a> </li> </ul> </nav> -
Modifier la vue
vueGenerale.phppour rajouter un pied de page comme<p> Site de covoiturage de ... </p> -
Rajoutez un style CSS minimaliste à votre page Web (clic droit puis “enregistrer la cible du lien sous…”). Ce style sera mis dans un dossier
css. Où mettre ce dossiercsssachant que nous interdisons l’accès internet à certaines parties du dossierTD5?Une façon de faire est de créer un dossier
TD5/ressourcesqui sera accessible sur internet (copiez le.htaccessdeweb), et qui contiendra le dossiercss, mais aussi plus tard des dossiersimgd’images etjspour le JavaScript.N’oubliez pas de rajouter la balise d’inclusion du CSS dans la section
headde la vue générale afin de charger le fichiernavstyle.css.<link rel="stylesheet" href="...">Déterminez le chemin à placer dans
href: le navigateur charge le fichiercontroleurFrontal.phpdepuis le dossierweb. Le fichier css se trouve un dossier plus haut, dansressources, puiscss.Remarque : il est probable que votre IDE affiche un warning car il ne connaît pas le chemin ciblé. C’est normal, de son point de vue, vous vous trouvez dans
src/vue/vueGenerale.php. Mais en réalité, le navigateur chargera la page web depuisweb. -
Ce fichier CSS rajoute aussi un style pour les formulaires. Pour l’appliquer, changez
formulaireCreation.phppour qu’un champ de formulaire s’obtienne par exemple avec<p class="InputAddOn"> <label class="InputAddOn-item" for="login_id">Login</label> <input class="InputAddOn-field" type="text" placeholder="Ex : leblancj" name="login" id="login_id" required> </p>
Concaténer des vues
Notre réorganisation nous permet aussi de résoudre le problème soulevé plus tôt à propos de la vue de création d’un utilisateur.
Nous souhaitons créer une vue utilisateurCree.php qui affiche le message
<p>L'utilisateur a bien été créé !</p>
avant de faire un require de liste.php puisque cette vue sert à écrire la liste
des utilisateurs. Ceci donnerait le visuel suivant.

-
Créez la vue
src/vue/utilisateur/utilisateurCree.phpcomme expliqué ci-dessus, en utilisant le concept de vue modulaire.
Remarque : La vueutilisateurCree.phpdoit faire deux lignes maintenant. -
Changez l’action
creerDepuisFormulairedu contrôleur pour appeler cette vue.
Attention : Il faut initialiser la variable$utilisateurscontenant le tableau de tous les utilisateurs afin qu’elle puisse être affichée dans la vue. -
Comme vous développez un site Web, il faut vérifier régulièrement sa conformité HTML et CSS. Faites-le maintenant.