3.4 La classe IhmBD 173 Voyons maintenant les principales méthodes de la classe IhmBD.Laméthode controle() prend en entrée un tableau associatif contenant les données d’une ligne de la table manipulée. Elle doit être appelée avant une mise à jour. Son rôle est de contrôler autant que possible que tout va bien se passer au moment de l’exécution de la requête. Bien entendu une partie des contrôles dépend de règles spécifiques à la table manipulées qui ne peuvent pas être codées de manière générique, mais on peut toujours contrôler la longueur ou le type des données en fonction du schéma de la table. On peut aussi « échapper » les apostrophes avec la méthode prepareChaine() de la classe BD. C’est cette dernière manipulation qui est effectuée dans le code ci-dessous, le reste étant à compléter. Comme la plupart des méthodes données par la suite, controle() s’appuie sur le tableau schema pour connaître le nom des attributs de la table et y accéder. // Méthode effectuant des contrôles avant mise à jour protected function controle($ligne) { $lignePropre = array () ; // On commence par traiter toutes les chaînes des attributs foreach ($this−>schemaTable as $nom => $options) { // Traitement des apostrophes $lignePropre [$nom] = $this−>bd−>prepareChaine( $ligne [$nom]) ; } // On peut , de plus , contrôler le type ou la longueur des // données d’ après le schéma de la table A faire ! return $lignePropre ; } La méthode controle() prend un tableau en entrée, copié du script appelant vers l’espace des variables de la fonction, et renvoie un tableau en sortie, copié de la fonction vers le script appelant. Si on a peur que cela nuise aux performances, il reste toujours possible de recourir à un passage par référence. La méthode formulaire() est donnée ci-dessous. Elle renvoie un formulaire adapté au mode de mise à jour à effectuer (insertion ou modification, voir page 78 pour les principes de création de ce type de formulaire). // Création d’un formulaire générique public function formulaire ($action , $ligne) { // Création de l ’objet formulaire $form = new Formulaire ("post" , $this−>nomScript , false ); $form−>champCache (" action " , $action ) ; $form−>debutTable() ; // Pour chaque attribut , création d ’un champ de saisie foreach ($this−>schemaTable as $nom => $options) { // D’abord vérifier que la valeur par défaut existe 174 Chapitre 3. Programmation objet if (! isSet($ligne [$nom])) $ligne[$nom] = "" ; // Attention : traitement des balises HTML avant // affichage $ligne [$nom] = htmlSpecialChars($ligne [$nom]) ; // On met la clé primaire en champ caché if ($options[ ’ cle_primaire ’] and $action == IhmBD:: MAJ_BD) { $form−>champCache ($nom , $ li g ne [ $nom ] ) ; } else { // Affichage du champ if ($options [ ’type ’] == "blob") $form−>champfenetre ($this−>entetes [$nom] , $nom , $ l ig ne [ $nom ] , 4, 30) ; else $form−>champTexte ( $this −>entetes [$nom] , $nom , $ li g ne [ $nom ] , $options [ ’longueur ’]) ; } } $form−>finTable() ; if ($action == IhmBD::MAJ_BD) $form−>champValider ("Modifier" , "submit"); else $form−>champValider ("Insérer" , "submit"); return $form−>formulaireHTML() ; } Noter l’utilisation de la fonction htmlSpecialChars() pour traiter les données venant de la base afin d’éviter les inconvénients résultant de la présence de balises HTML dans ces données (sujet traité page 64). La méthode utilise bien entendu la classe Formulaire pour aligner régulièrement chaque champ avec son en-tête. De même, la méthode tableau() ci-dessous s’appuie sur un objet de la classe Tableau. Là aussi on prend soin d’appliquer htmlSpecialChars() aux données provenant de la base. // Création d’un tableau générique public function tableau($attributs=array ()) { // Création de l ’objet Tableau $tableau = new Tableau(2, $attributs); $tableau−>setCouleurImpaire("silver ") ; $tableau−>setAfficheEntete(1, false); // Texte des en− têtes foreach ($this−>schemaTable as $nom => $options) $tableau−>aj ou tE nt et e (2 , $nom , $t h i s −>entetes [$nom]) ; 3.4 La classe IhmBD 175 $tableau−>ajoutEntete(2, "action" , "Action") ; // Parcours de la table $ r eq ue t e = "SELECT ∗ FROM $ t h i s −>nomTable" ; $resultat = $this−>bd−>execRequete ( $requete ) ; $i=0; while ($ligne = $this−>bd−>ligneSuivante ( $resultat )) { $i++; // Création des cellules foreach ($this−>schemaTable as $nom => $options) { // Attention : traitement des balises HTML avant affichage $ligne [$nom] = htmlSpecialChars($ligne [$nom]) ; $tableau−>ajoutValeur($i , $nom, $ligne [$nom]) ; } // Création de l ’URL de modification $urlMod = $this−>accesCle($ligne) . "& action=" . IhmBD:: EDITER ; $modLink = "<a href =’ $this −>nomScript?$urlMod’>modifier </a>"; $tableau−>ajoutValeur($i , "action" , $modLink) ; } // Retour de la chaîne contenant le tableau return $tableau−>tableauHTML () ; } Je laisse le lecteur consulter directement le code des méthodes accesCle(), insertion(), maj() et chercheLigne() qui construisent simplement des requêtes SQL SELECT, INSERT ou UPDATE en fonction du schéma de la table et des don- nées passées en paramètre. La dernière méthode intéressante est genererIHM() qui définit les interactions avec le formulaire et le tableau. Trois actions sont pos- sibles : 1. on a utilisé le formulaire pour effectuer une insertion : dans ce cas on exécute la méthode insertion() avec les données reçues par HTTP ; 2. on a utilisé le formulaire pour effectuer une mise à jour : dans ce cas on exécute la méthode maj() ; 3. on a utilisé l’ancre modifier du tableau pour éditer une ligne et la modifier : dans ce cas on appelle le formulaire en mise à jour. Si le formulaire n’est pas utilisé en mise à jour, on l’affiche en mode insertion. Dans tous les cas, on affiche le tableau contenant les lignes, ce qui donne le code suivant : 176 Chapitre 3. Programmation objet public function genererIHM ($paramsHTTP) { // A−t ’on demandé une action? if ( is Set ($paramsHTTP[ ’ action ’ ]) ) $action = $paramsHTTP[ ’ action ’ ] ; else $action = ""; $affichage = ""; switch ($action) { case IhmBD : : INS_BD : // On a demandé une insertion $this−>inse r t i on ($paramsHTTP) ; $affichage .= "<i>Insertion effectuée .</i>"; break ; case IhmBD : : MAJ_BD : // On a demandé une modification $this−>maj ($paramsHTTP) ; $affichage .= "<i>Mise à jour effectuée .</i>"; break ; case IhmBD : : EDITER : // On a demandé l ’accès à une ligne en mise à jour $ligne = $this−>chercheLigne ($paramsHTTP) ; $affichage .= $this−>formulaire(IhmBD::MAJ_BD, $ligne); break ; } // Affichage du formulaire en insertion si on n’a pas édité // en mise à jour if ( $a c t i o n != IhmBD : : EDITER) { $affichage .= "<h2>Saisie </h2>"; $affichage .= $this−>formulaire(IhmBD::INS_BD, array ()) ; } // On met toujours le tableau du contenu de la table $affichage .= "<h2>Contenu de la table <i>$this−>nomTable </ i> </h2>" .$this−>tableau(array("border" => 2)); // Retour de la page HTML return $affichage ; } Cette classe fournit ainsi une version « par défaut » des fonctionnalités d’accès à une table, version qui peut suffire pour élaborer rapidement une interface. Pour des besoins plus sophistiqués, il est possible de spécialiser cette classe pour l’adapter aux contraintes et règles de manipulation d’une table particulière. Le chapitre 5 donne un exemple complet d’une telle spécialisation (voir page 267). À titre de mise en bouche, voici la sous-classe IhmCarte qui surcharge la méthode formulaire() pour présenter les types de plat sous la forme d’une liste déroulante. 3.4 La classe IhmBD 177 Exemple 3.11 exemples/IhmCarte.php : La sous-classe IhmCarte <? require_once("IhmBD. class .php"); // Classe étendant IhmBD, spécialisée pour la table Carte class IhmCarte extends IhmBD { // La carte est caractérisée par les types de plats autorisés private $typesAutorises = array("EntrÈe" => "EntrÈe" , "Plat" => "Plat" , "Dessert" => "Dessert"); // Le constructeur de la classe . Attention à bien penser // à appeler le constructeur de la super−classe. function __construct($nomTable , $bd , $script="moi") { // Appel du constructeur de IhmBD parent :: __construct($nomTable , $bd , $script ); // On peut placer les entÍtes dËs maintenant $this−>en te t e s [ ’ id_choix ’ ] = "NumÈro du p la t " ; $this−>entetes [ ’ libelle ’] = "LibellÈ du plat"; $this−>entetes [ ’type ’] = "Type du plat"; } /∗ ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ Partie publique ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ ∗ / // Redéfinition du formulaire public function formulaire ($action , $ligne) { // Création de l ’objet formulaire $form = new Formulaire (" get " , $this −>nomScript , false); $form−>champCache (" action " , $action ) ; $form−>debutTable() ; // En mise à jour , la clé est cachée , sinon elle est saisissable if ($action == IhmBD::MAJ_BD) $form−>champCache (" id_choix" , $ligne [ ’id_choix ’ ]) ; else $form−>champTexte( $this −>entetes [ ’id_choix ’ ] , ’ id_choix ’ , "" , 4) ; // Vérifier que la valeur par défaut existe if (!isSet($ligne[ ’ libelle ’])) $ligne[ ’libelle ’] = ""; if (! isSet($ligne [ ’type ’ ])) $ligne[ ’type ’ ] = "Entrée"; $form−>champTexte ( $this −>entetes[ ’libelle ’], "libelle" , . méthode prepareChaine() de la classe BD. C’est cette dernière manipulation qui est effectuée dans le code ci-dessous, le reste étant à compléter. Comme la plupart des méthodes données par la suite,. méthode formulaire() est donnée ci-dessous. Elle renvoie un formulaire adapté au mode de mise à jour à effectuer (insertion ou modification, voir page 78 pour les principes de création de ce type de. ; } // Retour de la chaîne contenant le tableau return $tableau−>tableauHTML () ; } Je laisse le lecteur consulter directement le code des méthodes accesCle(), insertion(), maj() et chercheLigne()