CORRIGES DES TDS INFORMATIQUE WEB
pour la licence SEN (Sciences Exactes et Naturelles)
gilles.hunault@univ-angers.fr
Table des matières
Corrigé du TD numéro 1 Langage XHTML et CSS
Corrigé du TD numéro 2 CSS, formulaires, Javascript
Corrigé du TD numéro 3 Javascript
Corrigé du TD numéro 4 Php
Corrigé du TD numéro 5 Php et Mysql
Corrigé du TD numéro 6 Tout à la fois
Corrigé du TD DSCS numéro 1 (énoncé) Langage XHTML et CSS
HTML signifie HyperText Markup Language, c'est à dire Langage à Marqueurs d'Hyper Texte. Les marqueurs sont les symboles < (inférieur), > (supérieur), & (é commercial), / (slash) et ; (point-virgule). Les marqueurs / < et > définissent des balises ouvrantes et fermantes ou auto-fermantes, les marqueurs & et ; définissent les entités. Dans d'autres systèmes de marqueurs comme RTF ou LaTeX, on utilise \ (antislash) et les accolades { et }. Pour écrire en XHTML < (inférieur) et > (supérieur) on utilise les entités < et >. & est écrit via l'entité &.
La seule question qui se pose est de savoir comment passer d'une ligne à l'autre, d'où les différentes solutions proposées.Voici le code-source correspondant (le résultat en ligne est là) :
<h1>Solution 1 : des paragraphes</h1> <p>Bonjour.</p> <p>Bonsoir.</p> <h1>Solution 2 : des titres</h1> <h2>Bonjour.</h2> <h2>Bonsoir.</h2> <h1>Solution 3 : un retour à la ligne</h1> <p>Bonjour.<br /> Bonsoir.</p> <h1>Solution 4 : des divisions</h1> <div> Bonjour. </div> <div> Bonsoir. </div> <h1>Solution 5 : un tableau</h1> <table> <tr><td>Bonjour.</td></tr> <tr><td>Bonsoir.</td></tr> </table>Une page Web comporte des éléments. Les éléments peuvent avoir des attributs. Les attributs permettent d'identifier et mettre en forme les éléments. Les balises sont des repères et servent à délimiter les éléments, à l'aide de balises ouvrantes et fermantes, sauf pour les éléments auto-fermants qui n'utilisent qu'une balise, à la fois ouvrante et fermante. Les entités servent à écrire des caractères spéciaux, dont les symboles de marqueur de balise et d'entité (pour éviter que le navigateur ne les interprète). Dans une page Web les éléments sont emboités (imbriqués) hiérarchiquement de la façon suivante : l'élément html contient les deux éléments head et body. L'élément head contient l'élément title, le ou les éléments link pour les feuilles de style. L'élément body contient le "corps du texte affiché", avec ses élements div, p, table, ol, ul, dd... Les éléments sont repérés par une balise ouvrante et une balise fermante et ils ont un contenu (texte). Si le contenu est vide, on peut raccourcir en une balise ouvrante-fermante (nommée aussi auto-fermante). Par exemple l'élément hr commence par <hr> et se finit par </hr>. Au lieu d'écrire <hr></hr> on raccourcit en <hr />.
Les attributs sont des couples (propriétés,valeur) qui permettent de gérer les éléments (forme, identification, nommage, source). En transitionnel on peut utiliser de nombreuses propriétés de mise en forme. En strict on ne peut pas utiliser des attributs de mise en forme et donc en strict on doit passer par des attributs class pour indiquer quel style on utilise. Une entité est juste un raccourci pour permettre l'écriture des marqueurs et des symboles spéciaux.
Il est très important de bien structurer car sinon le navigateur risque de ne pas être capable d'afficher. Ce n'est pas obligatoire pour l'instant, mais c'est presque aussi risqué que de passer au rouge avec sa voiture !
Dés qu'on utilise une grammaire, on peut vérifier si le document est bien structuré et valide. Pourquoi s'en priver ? Ce n'est pas obligatoire non plus pour l'instant, et là encore c'est presque aussi risqué que de passer au rouge avec sa voiture.
Fermer une balise et fermer un élément ce n'est pas la même chose. Par exemple pour un paragraphe, il faut deux balises, une balise ouvrante de paragraphe et une balise fermante de paragraphe. Fermer la balise ouvrante p, c'est mettre le symbole > après p ; fermer la balise fermante p, c'est mettre le symbole > après /p. Donc pour l'élement p on a une ouverture d'élement avec l'ouverture et la fermeture de la balise ouvrante et on a aussi l'ouverture et la fermeture de la balise fermante pour fermer l'élément. Ouf !
Il existe plusieurs grammaires, comme :
- HTML 4.01 (versions strict, transitional, frameset)
- XHTML 1.0 (versions strict, transitional, frameset)
- XHTML 1.1
Et bien d'autres, avec MathML, SVG... Pour les grammaires conseillées ici (XHTML 1.0 strict et transitional), le vocabulaire est restreint au nom des élements html head body title link div p table tr td ul ol li span... ; les règles de syntaxe sont simples :
- toute balise ouverte doit être fermée.
- tout élément de balise et d'attribut doit être écrit en minuscules.
- le chevauchement entre balises est interdit.
- la valeur d'un attribut doit être mise entre "guillemets" même pour du numérique.
- l'abréviation des attributs est interdite.
- l'utilisation d'une DTD (Document Type Definition) XHTML est obligatoire.
On décide d'utiliser un seul paragraphe et des retours à la ligne (élément br) parce que comme cela on pourra gérer globalement tout le texte à l'intérieur (taille des caractères par exemple). Avec la grammaire transitionnelle, on peut utiliser l'attribut align de l'élément p pour centrer le(s) paragraphes, l'attribut size de l'élément font pour la taille. On peut définir la couleur avec l'attribut color de l'élément font et gérer l'interligne par un style "à la volée" via l'attribut style de l'élément p afin de gérer la propriété line-height. Enfin, pour le gras, aucune difficulté, il existe un élément b. Voir sen_adr1.htm dont voici le code-source :
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title> Adresse sur enveloppe A4 </title> </head> <body> <p style="line-height:100pt" align="center"> <font size="7" color="blue">Jean DUPONT</font><br /> <font size="7">3 route de Rome</font><br /> <font size="7">49100 <b>ANGERS</b></font> </p> </body> </html>Avec la grammaire stricte, l'attribut align n'est pas autorisé, pas plus que size et color. On crée donc un style, disons sen_adr2.css qui contient
p { line-height : 100pt ; text-align : center ; font-size : 300% ; } /* fin de définition de p */ .bleu { color : blue ; }On peut ensuite prévenir le navigateur qu'il faut utiliser ce fichier de style via l'élément link, et on n'a qu'a spécifier avec l'élément span qu'on veut le nom et le prénom en bleu à l'aide du nom du style mis comme valeur de l'attribut class. Voir sen_adr2.htm. dont voici le code-source :
<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr"> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <link rel="stylesheet" type="text/css" href="sen_adr2.css" title="essai" /> <title> Adresse sur enveloppe A4 </title> </head> <body> <p> <span class="bleu">Jean DUPONT</span><br /> 3 route de Rome<br /> 49100 <b>ANGERS</b> </p> </body> </html>Voici le texte et sa traduction (rappel: en XHTML, les éléments et les attributs s'écrivent en minuscule).
<x1 x2="X3" x4="x5">X6<x7 /><b>X8</b></x1> <p id="mfp" class="texte">Bonjour<hr /><b>tout le monde</b></p>Il y a 4 saisons avec une date de début et une date de fin (qui changent parfois d'une année à l'autre, voir echo l'article saison de Wikipedia). Pour avoir un même affichage pour les 4 saisons il faut utiliser la même mise en forme, interne ou externe, par propriété directe ou par style. Le plus "économique" est d'utiliser un style, interne ou externe. Ainsi le texte "brut" Printemps 20 mars 21 juin Ete 22 juin 22 septembre Automne 23 septembre 20 décembre Hiver 21 décembre 19 mars doit être décomposé en trois parties (nom, date de début, date de fin). La structuration en tableau peut s'écrire :
<table border="0"> <tr> <th>Nom de la saison</th> <th>Date de début</th> <th>Date de fin</th> </tr> <tr> <td>Printemps</td> <td>20 mars</td> <td>21 juin</td> </tr> <tr> <td>Ete</td> <td>22 juin</td> <td>22 septembre</td> </tr> <tr> <td>Automne</td> <td>23 septembre</td> <td>20 décembre</td> </tr> <tr> <td>Hiver</td> <td>21 décembre</td> <td>19 mars</td> </tr> </table>Avec une liste de définitions, on écrira :
<dl> <dt>Printemps</dt> <dd>20 mars<br />21 juin</dd> <dt>Ete</dt> <dd>22 juin<br />22 septembre</dd> <dt>Automne</dt> <dd>23 septembre<br />20 décembre</dd> <dt>Hiver</dt> <dd>21 décembre<br />19 mars</dd> </dl>Avec le tableau, il suffit de donner à l'attribut border une valeur non nulle pour avoir un quadrillage des cellules. Si on invente le style bleu qui définit la couleur des caractères comme "blue", il suffit de mettre une division avec ce style bleu autour du tableau ou de la liste pour tout avoir en bleu. On trouvera à l'adresse sen_saisons.htm une démonstration de ces possibilités.
Pour justifier un paragraphe, il faut utiliser la propriété text-align ; les valeurs possibles sont left, center, right, et justify. Les autres propriétés sont text-indent, line-height vertical-align et white-space. On peut jouer aussi sur l'espacement des mots et des lettres (propriétés word-spacing et letter-spacing), sur la décoration (souligné, clignotant, en petites majuscules...) avec les propriétés text-decoration, text-shadow et text-transform. Enfin, un paragraphe étant une boite, toutes les propriétés de boites s'appliquent, comme les tailles (width height), les positionnements (float clear left top right bottom), les marges (margin-top margin-right margin-left margin-bottom), les espaces intéreurs (padding-top padding-right padding-left padding-bottom), les bordures (border-top border-right border-left border-bottom border-top-width border-right-width border-left-width border-bottom-width border-color border-style), la visibilité (visibility display z-index overflow clip). Ouf !
La syntaxe est sélecteur { définition(s) de propriétés }. Un sélecteur est un nom d'élément existant (comme h2) ou un nom inventé (comme monmien .monmien et #monmien), ou un mix des deux comme (h2.momien et h2, monmien et h2 > monmien). Les définitions de propriétés sont séparées par des virgules. Il est faux de croire qu'on n'a qu'une seule valeur par propriété. Par exemple les marges ont une propriété margin qui regroupe les 4 propriétés margin-top margin-right margin-left margin-bottom et on peut spécifier les 4 propriétés d'un coup, comme par exemple margin : 10 20 30 40.
Oui, on peut mettre plusieurs attributs à condition qu'ils aient des noms différents. Ainsi <p id='oui' id='non'... est interdit mais <p id='oui' name='non'... est autorisé. Il ne faut pas confondre avec la notion de valeurs multiples pour un attribut. Ainsi <p class='oui' class='non'... est interdit mais <p class='oui non'... est autorisé. <p class='non oui'... est autorisé aussi, mais ne fournit pas forcément le même rendu.
Cascade signifie qu'on peut avoir plusieurs noms de style en même temps, que les valeurs des propriétés peuvent être définies en divers endroits (en local, en externe, dans le conteneur, dans le conteneur du conteneur...). Un exemple explicite est <p class='oui non'... avec certaines des propriétés par défaut de p redéfinies dans la ou les feuilles de style liées à la page.
Au vu de l'extrait de balise suivante
<p id="dates" name="dates" style="font-size : 5 ; color : blue" class="mamf1 mamf2"...le navigateur repère qu'il s'agit d'un élément p, lui donne la chaine de caractères 'dates' comme identifiant et comme nom. Si la grammaire est 'strict', le navigateur cherche alors dans la cascade des styles les noms mamf1 mamf2 et applique alors dans l'ordre des styles les propriétés correspondantes. Si la grammaire est 'transitionnal', le navigateur commence par mettre pour les propriétés indiquées dans le style local les valeurs fournies avant de chercher à appliquer les styles noms mamf1 et mamf2.
Pour les adresses de pages (ou URL, URI), on utilise une technique nommée URL-encodage qui est différente de la technique des entités. Ainsi é se note %E9% et donc au lieu de l'adresse http://www.google.fr/search?q=légumes il faut mettre dans l'ancre http://www.google.fr/search?q=l%E9gumes. Plus de détails sur le coin des experts.
Corrigé du TD DSCS numéro 2 (énoncé) CSS, formulaires, Javascript
Voici le texte et sa traduction (rappel: en XHTML, les éléments et les attributs s'écrivent en minuscule).
<x1 class="s1"> <x2 class="s2">...</x2> <x3 class="s3">...</x3> ... </x1> <ul class="s1"> <li class="s2">...</li> <li class="s3">...</li> </ul>Une bonne indentation permet de relire le code-source plus facilement. De plus, en cas d'erreur de balise, d'attribut, comme les validateurs indiquent la ligne de l'erreur, si on n'a qu'une balise par ligne, on sait tout de suite d'où vient l'erreur. Par contre si on écrit <x1><x2>x3> ou <table><tr>td> il est difficile de voir immédiatement quelle balise est incriminée (ici, c'est le troisième élément qui n'a pas de < dans les deux cas).
Pour écrire des indices et des exposants, il faut utiliser respectivement les élements sub et sup. Attention à l'ordre car il est d'usage de mettre l'indice avant l'exposant. Les exposants d'exposant et les indices d'indices sont autorisés comme pour :
abcd et xijk qui s'écrivent a<sup>b<sup>c<sup>d</sup></sup></sup> et x<sub>i<sub>j<sub>k</sub></sub></sub>
Deux styles suffisent : le bord du tableau (via table) et celui des cellules (via td). Pour tout centrer, on peut utiliser une boite conteneur (div) avec un style adapté. On consultera le code-source de l'énoncé pour voir la solution, qui ressemble à :
<div class='centre taille_5'> <table class='gbbec'> <tr> <td class='bbcf'>Angers </td> <td class='bbcf'>Nantes </td> <td class='bbcf'>Tours</td> <td class='bbcf'>Lyon</td> </tr> <tr> <td class='bbcf'>Oui</td> <td class='bbcf'>Non</td> ...Toutefois, la première fois qu'on fait cet exercice, le quadrillage n'est en général pas correct car il n'y a pas fusion des bords et malheureusement le tableau ressemble à :
Angers Nantes Tours Lyon Oui Non Oui Oui Standard Standard Spécial Spécial Janvier Février Mars Avril Il faut utiliser la propriété border-collapse pour forcer cette fusion. Voici donc les instructions correctes de style pour réaliser ce quadrillage :
/* gros bord bleu foncé épais avec "collapse" */ .gbbec { border : thick #000088 solid ; border-collapse : collapse } /* bord bleu clair fin */ .bbcf { border : thin #3399ff solid ; } /* bord bleu clair fin pointillé */ .bbcfp { border : thin #3399ff dashed ; }Oui, il y a une valeur par défaut, c'est 5 (indiquée par value). Pour xhtml transitionnel, il manque juste l'attribut action de l'élément form. On peut mettre action ="" même si c'est stupide... car le navigateur reprendra la page en effaçant la valeur entrée pour remettre 5 (la valeur par défaut). Il vaudrait mieux mettre une "vraie" adresse, comme par exemple action='http://forge.info.univ-angers.fr/scripts/mget.rex' histoire de savoir ce que la machine a compris. Il manque aussi l'indication de méthode (get ou post), un bouton 'submit' même si la touche ENTREE suffit à soumettre le formulaire. Il manque également un identifiant (id) et le nom (name) du champ d'entrée. Enfin et surtout, intellectuellement, il manque le texte de la question !
Voici donc un texte de formulaire plus correct :
<form action="http://forge.info.univ-angers.fr/scripts/mget.rex" method="get"> A quel age avez appris à lire ? <input type="text" value="5" name="age" id="age" /> ans <input type="submit" /> </form>Rappel : name sert pour envoyer les informations au serveur : sans name, le navigateur n'envoie que l'URL de l'action ; id sert à identifier le champ (pour que Javascript s'en serve, par exemple). Sans id, le navigateur envoie quand même ce qu'il faut (si name est présent).
Il faudrait utiliser un champ caché (hidden). Par exemple : <input type='hidden' value='grande' name='section' id='section' />
L'URL envoyée serait http://pdrv.fr/parm?JOUR=lun&DR=2&HR=A. Elle est composée de l'URL définie dans l'action, suivie du symbole ? puis des couples (variable,valeur) écrits variable=valeur, couples séparés par un &. Si on met x=2, il y a urlencodage (conversion) par le navigateur en x%3D2. De même, le bouton d'envoi sera transmis comme go=envoi.
L'ordre est celui des noms de champs dans le formulaire. Rien n'empêche d'avoir des noms identiques en majuscules et en minuscules mais c'est une mauvaise pratique car cela risque d'embrouiller le programmeur. Deux variables qui différent seulement par la casse majuscule/minuscule désignent des objets différents. On peut avoir un attribut value dans un élément input sans avoir d'attribut name ; cela arrive souvent quand on veut mettre un texte choisi pour la soumission (input type='submit'). Voir le code-source de sen_pdrv.php.
Comme l'attribut l'indique, type='text', il s'agit d'un texte qui est envoyé, c'est à dire une chaine de caractères. On peut essayer de la convertir en nombre, si besoin est, mais au départ c'est bien une chaine de caractères. Pour que Javascript convertisse en nombre, on utilise parseInt pour obtenir un entier et parseFloat pour obtenir un nombre réel. Par exemple avec un champ input type='text' name='age'... on écrirait en Javascript : valeur_age = parseInt(age.value,10)...
La valeur transmise est liée à l'attribut value. La valeur par défaut se définit via l'attribut selected. Pour des sélections multiples, on utilise l'attribut multiple. Et dans ce cas, le navigateur envoie plusieurs fois VARIABLE=VALEUR. Voici le fragment du formulaire correspondant :
<select name='SEXE' multiple='multiple'> <option value='G' >Pipounet</option> <option value='F' selected='selected'>Pipounette</option> </select>La valeur transmise est liée à l'attribut value. La valeur par défaut se définit via l'attribut checked. On ne devrait pas avoir deux valeurs par défaut (mais dans ce cas, les navigateurs semblent souvent utiliser le dernier attribut checked fourni). Voici le fragment du formulaire correspondant :
<input type='radio' value='1' name='pipouyou' /> Non <input type='radio' value='2' name='pipouyou' checked='checked'/> OuiSi le nombre 13 est plus petit que le nombre 19, en revanche la chaine de caractères '3' est plus grande que la chaine de caractères '21'. Car pour les chaines de caractères la relation d'ordre est l'ordre alphabétique et on compare d'abord les premiers caractéres puis les deuxièmes etc. donc ici avec '3' et '2' on en déduit que '2' est avant '3', comme avec 'b' et 'c'. Il faut en général convertir en Javascript à l'aide de parseInt les valeurs issues de formulaires pour en faire de 'vrais' nombres.
Les évènements claviers et souris sont nombreux, dont :
Clavier Souris Autre onKeyDown onMouseDown onLoad onKeyPress onClick onUnload onKeyup onMouseUp onChange onDblClick onReset onMouseOver onSubmit Dans la mesure où on ne sait pas si l'utilisateur a appuyé sur ENTREE ou s'il a cliqué sur le bouton ENVOI, ou sur une image, il vaut mieux utiliser onSubmit plutot que onClick. Remarque : si la fonction Javascript de validation renvoie la valeur false alors l'action associée au formulaire n'est pas exécutée.
Il y a beaucoup de choses à faire dans les deux cas. Pour une liste d'entiers, il faut tester qu'il n'y a que des espaces et des chiffres, ce qui n'est pas simple (sauf à utiliser des 'expressions régulières') car il faut passer en revue tous les caractères saisis. Pour le ballon rouge, accepte-t-on les réponses en majuscules ? et si la réponse est roug au lieu de rouge (c'est à dire s'il manque une lettre), peut-on considérer que c'est faux (intellectuellement, pédagogiquement, bien sur car informatiquement, avec une lettre de différent, tout est faux). Idem pour la ballon rouge. Donc l'évaluation, c'est difficile avec un ordinateur.
Corrigé du TD DSCS numéro 3 (énoncé) Javascript
A la ligne 5, la machine calcule f(0) ce qui donne 1 donc c vaut 1. On passe donc dans le alors du si, soit la ligne 7. Comme g(1) vaut 2, Javascript écrit dans la page le texte
on Trouve 2Pour les plus pointilleux et les plus pointilleuses, il y a un espace avant on, un espace avant 2 et le t de on trouve est en majuscule.
Une erreur en XHTML n'est pas toujours grave.
Pour Google, c'est <a href=http://www.google.fr>ici</a>, le navigateur "comprend" qu'il s'agit d'une URL et le lien est quand même valide.
Pour Google, c'est <a href="http://www.google.fr>ici</a>, le navigateur va attendre de trouver un guillemet pour fermer l'URL et cela risque d'être catastrophique pour la page.
Pour Google, c'est <a href=http://www.google.fr">ici</a>, le navigateur va essayer d'ouvrir l'URL avec le guillement en fin d'URL et Google dira que la page www.google.fr/%22 n'existe pas....
Contrairement à XHTML, une erreur de guillemet en Javascript est toujours grave et provoque l'abandon de l'instruction, de la fonction voire même du fichier impliqué. On ne s'en rend pas toujours compte car le navigateur quitte Javascript mais continue à interpréter le reste de la page...
En conclusion, il faut être très rigoureux (rigoureuse) et très pointilleuse (pointilleux) sur la syntaxe de tout ce qu'on écrit, savoir quand les guillemets, points-virgules et autres accolades sont obligatoires...
Il faut créer un élément de type H1, lui mettre Bonsoir comme contenu puis l'insérer dans l'élément body. En d'autre termes, il faut définir ce nouveau H1 comme un nouvel enfant de body. Enfin, il faut lui affecter comme attribut class la valeur cadre. La solution est nommée td3exo3.htm et le fichier javascript chargé dans l'élément head se nomme td3xo3.js ; il définit une fonction nommée ajout appelée dans le onclick. Et voilà !
Avec window.document.write, Javascript écrit dans le document à l'endroit où les instructions Javascript sont appelées. On consultera sen_dm.php pour la correction de l'exercice avec son fichier sen_dm.js ; même si une fonction n'est pas indispensable, c'est quand même "plus propre" d'utiliser une fonction mis dans un fichier externe. Rappel : les fonctions se chargent en général via <script src=...> dans head et l'exécution de la fonction f se fait à l'endroit où on appelle la fonction via <script type='text/javascrip'>f(..)</script>
Pour trouver le maximum, on initialise avec la première valeur du tableau (c'est plus propre qu'avec 0 ou -1 ou 123456789) et on passe en revue les éléments à l'aide d'une boucle pour. Quand le nombre courant est plus grand que le maximum trouvé jusque là, on change de maximum. Voir la page sen_valmax.php et son fichier de script sen_valmax.js.
Si le tableau est déja trié, pas besoin de parcourir tout le tableau avec une boucle pour. Il suffit de se restreindre avec une boucle tant que aux premières valeurs égales du tableau. Voir la page sen_valmax2.php et son fichier de script sen_valmax2.js.
Le mot légumes peut poser problème à cause de l'accent sur le e. On utilise donc une table de correspondance entre les mots et les noms des fichiers-images. Pour l'appel de Google, on utilise la fonction encodeURI. Voir la page sen_ldc.php et son fichier de script sen_ldc.js.
Voici le texte des fonctions :
function h1(x) { window.document.write("<h1>" + x + "</h1>") ; } function h(i,x) { window.document.write("<h"+i+">" + x + "</h"+i+">") ; }Ce n'est pas une bonne idée de mettre trop de choses dans du Javascript car s'il n'est pas activé, l'utilisateur ne verra rien. L'intéret de mettre h1(x) (implémenté directement ou via h(1,x)) c'est d'accélérer la frappe, d'avoir des balises ouvrantes et fermantes gérées par fonction, ce qui est plus "sur" que de laisser l'utilisateur les ouvrir et les fermer. On pourra tester ici le fichier de script sen_h1.js.
Corrigé du TD DSCS numéro 4 (énoncé) Php
Consulter std.php pour le texte des fonctions demandées (et bien d'autres). On peut y lire :
# fonction générale pour titre de niveau i function h($nivi,$chen=" ",$cla="") { if ($cla=="") { echo "<h$nivi> $chen </h$nivi>\n" ; } else { echo "<h$nivi class='$cla'> $chen </h$nivi>\n" ; } ; # fin de si } ; # fin de fonction h1 # titre de niveau 1 function h1($chen=" ",$cla="") { h("1",$chen,$cla) ; } ; # fin de fonction h1 # titre de niveau 2 function h2($chen=" ",$cla="") { h("2",$chen,$cla) ; } ; # fin de fonction h2 # titre de niveau 3 function h3($chen=" ",$cla="") { h("3",$chen,$cla) ; } ; # fin de fonction h3 # fonctions simplistes pour titres de niveau 1 et 2 function hh1($chen=" ") { echo "<h1>$chen</h1>" ; } function hh2($chen=" ") { echo "<h2>$chen</h2>" ; }L'intérêt d'une seule fonction pour tous les titres est multiple : c'est PHP qui ouvre et ferme les balises, c'est plus "conceptuel" car on ne voit plus directement les balises, c'est plus court à écrire et c'est valide. De plus toutes les appels des fonctions hi auront le même comportement puisqu'elles sont toutes écrites par la même fonction.
Pour les valeurs par défaut, les éléments h n'autorisent pas un contenu vide. Ecrire function h1($chen="") est donc une mauvaise idée, mettre function h1($chen=" ") est mieux. Par contre avoir un style non défini n'est pas gênant. Donc function h1($chen=" ",$cla="") est suffisant. Voici des fonctions b et href possibles :
function b($chen=" ") { return "<strong>$chen</strong>" ; } ; # fin de fonction b function href( $href , $nomh="",$cla="") { $defcla = "" ; if (strlen($cla)>0) { $defcla = "class='$cla'" ; } ; if ($nomh=="") { $nomh=$href ; } ; return "<a href=\"$href\" $defcla>$nomh</a>" ; } ; # fin de fonction hrefOn peut faire "bêtement" les affectations
$tabVilles = new Array() ; $tabVilles[0] = "Angers" ; $tabVilles[1] = "Nantes" ; $tabVilles[2] = "Rennes" ;Mais il existe une fonction pour cela, explode() :
$tabVilles = explode(" ","Angers Nantes Rennes") ;Si on consulte le code-source de ldc.php et de mesfonctions3.php on voit que la fonction ldc écrite en TP est conceptuelle car on n'y trouve aucune balise. La voici :
function ldc($laliste) { ################################## h1_version1("Ma liste de courses") ; $tde = explode(" ",$laliste) ; # tableau des éléments table('1','border : solid 3px #880000 ; background : #CCFFFF ; ') ; $nbe = count($tde) ; # nombre d'éléments for ($ide=0;$ide<$nbe;$ide++) { $element = $tde[$ide] ; tr() ; td("center") ; ancre("http://www.google.fr/search?q=".urlencode($element),$element) ; fintd() ; td("center") ; if ($element=="légumes") { $element2 = "legumes" ; } else { $element2 = $element ; } ; # fin de si ancre("sen_$element2.jpg",img("sen_$element2.jpg")) ; fintd() ; # en prime : un lien sur Google images td("center") ; ancre("http://images.google.fr/images?q=".urlencode($element),"images de $element") ; fintd() ; fintr() ; } ; # fin pour ide fintable() ; } ; # fin de fonction ldcVoici à quelque chose près le code XHTML correspondant :
<?xml version='1.0' encoding='ISO-8859-1' ?> <!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN'... <html xmlns='http://www.w3.org/1999/xhtml' lang='fr' xml:lang='fr'> <head> <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1' /> <title> LDC en php </title> </head> <body> <h1>Ma liste de courses</h1> <table border='1' style='border : solid 3px #880000 ; background : #CCFFFF ; '> <tr> <td align='center'> <a href='http://www.google.fr/search?q=pain'>pain</a> (google) </td> <td align='center'> <a href='sen_pain.jpg'><img src='sen_pain.jpg' alt='pain' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=pain'>images de 'pain'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=oeuf'>oeuf</a> (google) </td> <td align='center'> <a href='sen_oeuf.jpg'><img src='sen_oeuf.jpg' alt='oeuf' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=oeuf'>images de 'oeuf'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=viande'>viande</a> (google) </td> <td align='center'> <a href='sen_viande.jpg'><img src='sen_viande.jpg' alt='viande' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=viande'>images de 'viande'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=lait'>lait</a> (google) </td> <td align='center'> <a href='sen_lait.jpg'><img src='sen_lait.jpg' alt='lait' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=lait'>images de 'lait'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=vin'>vin</a> (google) </td> <td align='center'> <a href='sen_vin.jpg'><img src='sen_vin.jpg' alt='vin' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=vin'>images de 'vin'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=fromage'>fromage</a> (google) </td> <td align='center'> <a href='sen_fromage.jpg'><img src='sen_fromage.jpg' alt='fromage' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=fromage'>images de 'fromage'</a> </td> </tr> </table> <h1>Ma liste de courses</h1> <table border='1' style='border : solid 3px #880000 ; background : #CCFFFF ; '> <tr> <td align='center'> <a href='http://www.google.fr/search?q=tomates'>tomates</a> (google) </td> <td align='center'> <a href='sen_tomates.jpg'><img src='sen_tomates.jpg' alt='tomates' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=tomates'>images de 'tomates'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=saucisson'>saucisson</a> (google) </td> <td align='center'> <a href='sen_saucisson.jpg'><img src='sen_saucisson.jpg' alt='saucisson' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=saucisson'>images de 'saucisson'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=eau'>eau</a> (google) </td> <td align='center'> <a href='sen_eau.jpg'><img src='sen_eau.jpg' alt='eau' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=eau'>images de 'eau'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=l%E9gumes'>légumes</a> (google) </td> <td align='center'> <a href='sen_legumes.jpg'><img src='sen_legumes.jpg' alt='légumes' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=l%E9gumes'>images de 'légumes'</a> </td> </tr> <tr> <td align='center'> <a href='http://www.google.fr/search?q=bananes'>bananes</a> (google) </td> <td align='center'> <a href='sen_bananes.jpg'><img src='sen_bananes.jpg' alt='bananes' height='50' /></a></td> <td align='center'> <a href='http://images.google.fr/images?q=bananes'>images de 'bananes'</a> </td> </tr> </table> </body> </html>Corrigé du TD DSCS numéro 5 (énoncé) Php et Mysql
Voici les différentes réponses :
SELECT COUNT(evenement) FROM sen_HIST ; SELECT COUNT(evenement) FROM sen_HIST WHERE date < 1789 ; SELECT evenement FROM sen_HIST WHERE date < 1789 ; SELECT evenement FROM sen_HIST ORDER BY date LIMIT 2 ;Attention : la question sur les deux premières lignes de la table sans ordre de tri explicite est une question ambigue...
Voici les différentes réponses MySql :
SELECT COUNT(*) FROM sen_elv WHERE pren="Louise" ; SELECT COUNT(*) FROM sen_elv WHERE nume=1 ; SELECT AVG(note) FROM sen_elv WHERE pren="Louise" ; SELECT AVG(note) FROM sen_elv, sen_exer WHERE pren="Louise" AND mat="Calcul" AND nume=idexo ; SELECT pren, note FROM sen_elv WHERE nume=1 ORDER BY note DESC ; SELECT pren, AVG(note) AS moyenne FROM sen_elv,sen_exer WHERE nume=1 AND mat="Calcul" AND nume=idexo GROUP BY pren ORDER BY moyenne DESC ; SELECT DISTINCT(pren) FROM sen_elv,sen_exer WHERE nume=idexo AND diffi= 3 ;Malgré toute la bonne volonté du monde et quelles que soient vos compétences en Mysql, il n'est pas possible d'assurer un suivi pédagogique pour les faibles en maths. Avec aussi peu d'éléments qu'une note il est impossible de savoir d'où viennent les difficultés de l'apprenant.
Le texte PHP pour les comptages et l'affichage est ici et le sous-programme conceptuel est nommé combiens_inc.php ; il définit une fonction combien() qui accepte comme paramètres et dans cet ordre le nom de la table, le nom (facultatif) du champ et la condition (facultative), ce qui donne respectivement les 4 appels de la fonction combien suivants :
$rep = combien("sen_HIST") ; ... $rep = combien("sen_HIST","evenement","date < 1789") ; ... $rep = combien("sen_elv","*","pren='Louise'") ; ... $rep = combien("sen_elv","*","nume=1") ; ...Corrigé du TD DSCS numéro 6 (énoncé) Tout à la fois
Les lignes 8 et 9 réalisent une connexion au serveur de bases de données MySql nommé forge pour l'utilisateur anonymous et avec le mot de passe anonymous.
Les lignes 11 à 15 construisent le texte d'une requête MySql qui est : SELECT DISTINCT( mat ) AS lamat FROM sen_exer GROUP BY lamat ORDER BY lamat ;
La ligne 17 initialise une variable nommée $nummat qui va servir d'indice de numéro de matière pour le tableau nommé $tabmat déclaré à la ligne 18.
Les lignes 20 à 27 exécutent la requête et transfèrent son résultat dans le tableau $tabmat. Sachant que pour les données fournies le résultat de la requête est :
+----------+ | lamat | +----------+ | Calcul | | Histoire | +----------+le tableau $tabmat contient la chaine "Calcul" à l'indice 1 et "Histoire" à l'indice 2.
Les lignes 29 à 39 exécutent une boucle sur les éléments du tableau $tabmat. Pour chaque indice $idm de matière, on affiche un titre de niveau 2 (sortie exacte plus loin dans le corrigé) et on effectue une seconde boucle pour calculer le nombre d'exercices de la matière en difficulté 1, 2 ou 3. Une fois ce nombre $nbe calculé, il est affiché dans un paragraphe avec un retrait fourni par l'élément blockquote.
On obtient donc comme affichage le texte suivant
Matière numéro 1 : Calcul 2 exercices en difficulté 1 1 exercices en difficulté 2 1 exercices en difficulté 3 Matière numéro 2 : Histoire 2 exercices en difficulté 1 0 exercices en difficulté 2 1 exercices en difficulté 3Soit, en termes de balises :
<h2> Matière numéro 1 : Calcul </h2> <blockquote> <p> 2 exercices en difficulté 1 </p> </blockquote> <blockquote> <p> 1 exercices en difficulté 2 </p> </blockquote> <blockquote> <p> 1 exercices en difficulté 3 </p> </blockquote> <h2> Matière numéro 2 : Histoire </h2> <blockquote> <p> 2 exercices en difficulté 1 </p> </blockquote> <blockquote> <p> 0 exercices en difficulté 2 </p> </blockquote> <blockquote> <p> 1 exercices en difficulté 3 </p> </blockquote>Remarquons tout d'abord que le texte proposé ne peut pas être utilisé tel quel car il n'est pas valide pour la grammaire strict ; au lieu de <h1><font color="blue"> il faudra donc produire le texte <h1 class='fbleu'> après avoir défini le style fbleu.
Pour ne pas avoir à écrire le texte lié au titre des séries de cours deux fois (une fois dans la table des matières et une fois dans le titre des cours), l'énoncé indique d'utiliser une structure ; celle de tableau parait tout à fait indiquée et peut facilement être mise à jour si on a plus de deux séries. On pourra donc écrire en PHP :
$tabCours = array() ; $tabCours[1] = " le langage XHTML " ; $tabCours[2] = " les styles CSS " ; $nbc = count($tabCours) ; # attention : on n'utilise pas l'indice zéroOn peut aussi écrire les instructions suivantes qui permettent plus facilement de réordonner les séries :
$tabCours = array() ; $numCours = 0 ; $numCours++ ; $tabCours[$numCours] = " le langage XHTML " ; $numCours++ ; $tabCours[$numCours] = " les styles CSS " ; $nbc = count($tabCours) ; # attention : on n'utilise pas l'indice zéroUne simble boucle POUR avec une fonction licours écrite pour l'occasion permet alors de réaliser la table des matières en tant que liste non ordonnée :
h1("Table des matières","fbleu") ; ul() ; for ($idc=1;$idc<=$nbc;$idc++) { licours($idc,$tabCours[$idc]) ; } ; # fin pour idc finul() ;Et de même, pour réaliser le titre de chaque série, on invente une fonction nommée h2cours :
h2cours(1,$tabCours[1],"fvert") ; p() ; echo "..." ; finp() ; h2cours(2,$tabCours[2],"fvert") ; p() ; echo "..." ; finp() ;Voici le texte des fonctions utilisées (ce qui n'était pas demandé) :
function licours($num,$nom) { debutli() ; echo " série $num : ".ancre("#s$num",$nom) ; finli() ; } # fin de fonction tdDscs function h2cours($num,$nom,$cla) { h2("Série $num : $nom ",$cla) ; } # fin de fonction tdDscs function h1($chen=" ",$cla="") { h("1",$chen,$cla) ; } ; # fin de fonction h1 function h2($chen=" ",$cla="") { h("2",$chen,$cla) ; } ; # fin de fonction h2 function h($nivi,$chen=" ",$cla="") { if ($cla=="") { echo "<h$nivi> $chen </h$nivi>\n" ; } else { echo "<h$nivi class='$cla'> $chen </h$nivi>\n" ; } ; # fin de si } ; # fin de fonction h function ancre( $href , $nomh="" ) { if ($nomh=="") { $nomh=$href ; } ; return "<a href=\"$href\">$nomh</a>" ; } ; # fin de fonction ancre function debutli($cntli="") { echo "<li>$cntli" ; } ; # fin de fonction debutli function finli() { echo "</li>\n" ; } ; # fin de fonction finliPour construire le menu, il est prudent de procéder en deux étapes. Dans la première, on va demander à MySql de trouver et d'ordonner tous les couples (matière,difficulté) possibles avec au passage le calcul du nombre d'exercices associés. Dans la deuxième, PHP va mettre en forme ces valeurs, pour éviter d'avoir un affichage trop sommaire comme :
Calcul Difficulté 1 (5 exercices) Calcul Difficulté 2 (5 exercices) Calcul Difficulté 3 (3 exercices) Histoire Difficulté 1 (7 exercices) Histoire Difficulté 3 (6 exercices) ...A l'aide de la requête
SELECT mat,diffi,COUNT(idexo) AS nbe FROM sen_exer GROUP BY mat,diffi ORDER BY mat,diffi ;on obtient les informations demandées avec 3 champs nommés respectivement mat, diffi et nbe dont un exemple de sortie est :
+----------+-------+-----+ | mat | diffi | nbe | +----------+-------+-----+ | Calcul | 1 | 2 | | Calcul | 2 | 1 | | Calcul | 3 | 1 | | Histoire | 1 | 2 | | Histoire | 3 | 1 | +----------+-------+-----+Pour mettre en forme ces données, on va tester la valeur du champ mat : lorsque celui-ci change, il faut changer d'item de liste. On nomme matc la matière courante et ancmat la matière précédente, initialisée à la chaine vide. On initialise le numéro de matière courante nummat à 0 et on l'incrémente de 1 à chaque changement de matière.
Voici le programme correspondant :
<?php
include("../std.php") ;
debutPage("sen_matdiff","strict") ;
h1(" SEN : TD 6 EXO 3 ") ;
blockquote() ;
debutSection() ;
################################
mysql_connect("localhost","anonymous","anonymous") ;
mysql_select_db("statad") ;
$ch1 = "mat" ;
$ch2 = "diffi" ;
$ch3 = "nbe" ;
$que = "" ;
$que .= " SELECT $ch1 , $ch2, COUNT(idexo) AS $ch3 " ;
$que .= " FROM sen_exer " ;
$que .= " GROUP BY $ch1 , $ch2 " ;
$que .= " ORDER BY $ch1 , $ch2 ; " ;
$ancmat = "" ;
$nummat = 0 ;
# POUR VERIFICATION echo "$que\n" ;
$res = mysql_query($que) ;
while ($tdr=mysql_fetch_array($res)) {
$matc = $tdr[$ch1] ;
$dif = $tdr[$ch2] ;
$nbe = $tdr[$ch3] ;
# POUR VERIFICATION echo "<pre>$matc Difficulté $dif $nbe " ;
# POUR VERIFICATION echo "NUMMAT $nummat ANCMAT $ancmat\n</pre>" ;
if ($matc<>$ancmat) {
# c'est une nouvelle matière : on augmente le numéro nummat
# et on met un titre avec le nom de la matière
$nummat++ ;
h2("Matière $nummat : $matc") ;
} ; # fin de si
blockquote() ;
p() ;
echo "Difficulté $dif ($nbe exercices)" ;
finp() ;
finblockquote() ;
$ancmat = $matc ;
} ; # fin tant que
################################
finSection() ;
finblockquote() ;
finPage() ;
?>
Telle que nous l'avons écrite, la requête ne retourne que les couples (matière,difficulté) pour lesquels il y a au moins un exercice. Avec le programme de l'exercice 1, tous les couples (matière,difficulté) étaient affichés puisqu'on utilisait une boucle POUR afin de passer en revue tous les niveaux de difficulté d'une même matière.
Ce programme effectue deux séries de calcul à l'aide de la fonction calc. Pour la première série le tableau $elva correspondant aux données 10 et 10 ainsi que le paramètre 1 sont utilisés. Pour la deuxième série, le tableau $elvb correspondant aux données 2 et 18 ainsi que le paramètre 2 sont utilisés.
Une lecture attentive du fichier inclus montre qu'on calcule la somme des valeurs, leur moyenne et leur écart-type, ces deux dernières valeurs étant affichées avec deux décimales.
Au passage, on remarque que la moyenne seule ne permet pas de se rendre compte de la différence entre les notes des deux élèves. Voici ce qui est exactement affiché
Série numéro 1 la valeur 0 est 10 ; so vaut 10 la valeur 1 est 10 ; so vaut 20 s = 20, m = 10.00 ec = 0.00 Série numéro 2 la valeur 0 est 2 ; so vaut 2 la valeur 1 est 18 ; so vaut 20 s = 20, m = 10.00 ec = 8.00
Retour à la page principale de (gH)