Cpm Affiliation : la régie publicitaire au Cpm

Premier TP : une calculatrice avec le PHP

Alors que le douzième chapitre pointe le bout de son nez, il est temps de faire le point.
On a déjà vu ensemble une grande partie des bases du PHP : avec tout ce qu'on a vu, vous pouvez faire de belles choses. Dans la deuxième partie de ce tutoriel, on va tout mettre en pratique. Mais avant, on va faire un TP pour que vous puissiez juger vous-mêmes de l'état de vos connaissances.

Ce TP est également le dernier chapitre de la partie I, alors soyez attentifs.

Objectifs

Le but de ce TP est que vous réalisiez une calculatrice. Mais ne vous en faites pas, vous allez en faire une très simple.
Premièrement, parce que vous n'avez pas tous des notions en mathématiques suffisantes pour faire quelque chose de plus compliqué.
Deuxièmement et principalement parce que vous allez déjà en baver pour faire quelque chose de simple.
Je suis sûr que très peu d'entre vous réussiront à faire quelque chose qui fonctionne parfaitement.
Mais ne vous inquiétez pas, ce TP est difficile, c'est volontaire. Je veux que vous compreniez par vous-mêmes que vous n'êtes pas loin. Vous avez vu les bases, mais vous n'avez pas encore beaucoup pratiqué. Vous manquez donc cruellement d'expérience, et comme le dit le dicton : « C'est en forgeant qu'on devient forgeron. »

Ne soyez donc pas étonnés si vous pataugez dans la semoule tout au long de ce TP.

Cette calculatrice sera très simple, elle sera constituée d'un formulaire présentant deux petites zones de texte et une liste déroulante. Les zones de texte serviront au visiteur pour entrer les deux nombres qu'il veut traiter. On demandera à l'utilisateur d'entrer uniquement des nombres entiers. On pourrait prendre des nombres à virgule, mais je n'ai pas envie (et de toute façon, ça ne change rien !).
La liste déroulante donnera accès à cinq opérations, les opérations de base :

  • addition ;
  • soustraction ;
  • division ;
  • multiplication ;
  • modulo.

Une fois que le visiteur aura saisi les nombres et le type d'opération, votre script devra afficher le calcul et la réponse.

ATTENTION :Faites attention au cas où le visiteur voudrait diviser (ou faire le modulo) par zéro. En effet, en mathématiques, on ne peut pas diviser un nombre par zéro, ça donne un résultat indéfini. C'est pareil en PHP (et une erreur s'affichera).Vous devrez donc vérifier les nombres que le visiteur entrera. S'il veut diviser ou faire le modulo par zéro, vous devrez afficher un message : une erreur est survenue : vous ne pouvez pas diviser par zéro.

Toutefois, il y a une deuxième chose que vous devez vérifier. Certains navigateurs, via des extensions, permettent de modifier les formulaires (tout le code source HTML, même !). On peut donc modifier les attributs value et compagnie. C'est là qu'est le risque. Pour identifier quelle opération il faudra faire, vous mettrez des valeurs particulières dans les attributs value. Vous devrez donc vérifier que vous recevez une de ces valeurs, sans quoi vous devrez afficher le message : une erreur est survenue : opération indéfinie.

Si vous affichez une de ces deux erreurs, vous ne devrez pas afficher le calcul et la réponse.
Mais dans tous les cas, vous afficherez toujours le formulaire pour qu'on puisse faire d'autres calculs.

Quelques conseils

Avant tout, je vais vous imposer quelque chose : votre code devra être présenté d'une certaine façon. Je vais vous donner le squelette de votre code :

Code PHP :

<?php

/* Déclaration des constantes */

/* Déclaration des fonctions */

/* Traitement des données */

/* Affichage du calcul et du formulaire */

?>

Vous viendrez intercaler votre code dans ces commentaires. Si je fais ça, ce n'est pas pour vous embêter, j'ai mes raisons mais vous ne les connaîtrez pas tout de suite. Il est possible que certaines sections de code soient vides, par exemple la déclaration des constantes. Je vous le dis tout net : il n'y a pas besoin de constantes dans ce script. Mais gardez quand même le commentaire pour bien montrer que vous savez séparer votre code et le regrouper par « thème ».

Comme c'est votre premier TP, je vais être gentil et vous donner un aperçu en français de ce que sera votre code :

Code PHP :

<?php

/* Déclaration des constantes */
/* Déclaration des fonctions */
// Création d'une fonction qui prendra trois paramètres : les deux nombres sur lesquels on travaille et une information qui permettra de savoir quelle opération appliquer
// La fonction retournera soit une chaîne de caractères, soit le résultat du calcul
// Les chaînes de caractères que la fonction peut retourner sont les deux erreurs que j'ai mentionnées précédemment
// Vous devrez donc gérer ici les deux erreurs possibles
/* Traitement des données */
// Tout d'abord, vous allez vérifier si toutes les données existent et ne sont pas vides
// Pour vérifier si les variables existent, vous utiliserez l'une des deux fonctions qu'on a vues dans le chapitre sur les arrays
// Pour vérifier si les variables sont vides, regardez ce que retourne un : trim($var) != ''
// Si tout est OK, vous appellerez la fonction qu'on a déclarée plus tôt
// En fonction de ce que retourne la fonction, vous devrez vérifier si une erreur s'est produite
// Pour ce faire, il suffit de regarder quel est le type de valeur que la fonction nous retourne
// Si tout s'est bien passé, ça retourne un INT, sinon une STRING
// Pour vérifier si une expression est de type entier, on utilise la fonction is_int(). Pour vérifier si une expression est de type chaîne de caractères, on utilise la fonction is_string()
/* Affichage du calcul et du formulaire */
// Si le formulaire a été soumis, vous afficherez :
// soit une erreur si une erreur s'est produite,
// soit le calcul s'il n'y a pas eu d'erreur.
// Ensuite, vous afficherez le formulaire

?>

Et voilà, vous avez tout en mains.  En vous appuyant sur ces quelques commentaires et sur tout ce que vous devriez avoir appris jusqu'à présent, vous devriez arriver à faire ce que je vous demande.

Il ne me reste plus qu'à vous souhaiter bonne chance, et bon courage surtout. 

Correction !

Bon, si vous êtes là, c'est que soit vous avez brillamment réussi, soit vous vous êtes lamentablement plantés et vous cédez à la tentation.
Si vous n'avez pas réussi ce script, mais que vous avez cherché longtemps (plusieurs dizaines de minutes au moins, si pas des heures !), regardez la correction, ça vous aidera.
Par contre, si vous n'avez pas cherché, ne regardez pas ! Ça ne vous apportera rien du tout.

Code PHP :

<?php

error_reporting(E_ALL);

/* Déclaration des constantes */
/* Déclaration des fonctions */
function operation($a, $b, $operation)
{
if($operation == 0)
{
return $a + $b;
}
elseif($operation == 1)
{
return $a - $b;
}
elseif($operation == 2 )
{
return $a * $b;
}
elseif($operation && $operation < 5)
{
if($b != 0)
{
if($operation == 3)
{
return $a / $b;
}
elseif($operation == 4)
{
return $a % $b;
}
}
else
{
return 'Une erreur est survenue : vous ne pouvez pas diviser par zéro';
}
}
else
{
return 'Une erreur est survenue : opération indéfinie';
}
}
/* Traitement des données */
if(isset($_POST['a']) && trim($_POST['a']) != '' && isset($_POST['b']) && trim($_POST['b']) != '' && isset($_POST['operation']) && trim($_POST['operation']) != '')
{
$display = true;
$result = operation((int)$_POST['a'], (int)$_POST['b'], (int)$_POST['operation']);
$error = is_string($result);
if($_POST['operation'] == 0)
{
$signe = ' + ';
}
elseif($_POST['operation'] == 1)
{
$signe = ' - ';
}
elseif($_POST['operation'] == 2)
{
$signe = ' * ';
}
elseif($_POST['operation'] == 3)
{
$signe = ' / ';
}
else {
$signe = ' % ';
}
}
else
{
$display = false;
$result = false;
$error = false;
}
/* Affichage des résultats et du formulaire */
if($display)
{
if($error)
{
echo $result;
}
else
{
echo (int)$_POST['a'] . $signe . (int)$_POST['b'] . ' = ' . $result;
}
}
?>
<form action="index.php" method="post">
<p>
Opérande n°1 :<input type="text" name="a" />
<br />
Opérande n°2 :<input type="text" name="b" />
<br />
Opération :
<select name="operation">
<option value="0">Addition</option>
<option value="1">Soustraction</option>
<option value="2">Multiplication</option>
<option value="3">Division</option>
<option value="4">Modulo</option>
</select>
<br />
<input type="submit" value="Calculer" />
</p>
</form>

Pas si mal, ce code, hein ?
Vous avez dû obtenir un code proche, mais si vous n'avez pas la même chose, ce n'est pas grave. C'est même normal. Le but du jeu, pour le moment, c'est que le script fonctionne. Je n'ai pas mis de commentaires.
Il y a deux raisons à cela.
La première, c'est que le script est ridiculement simple et court.
La seconde, c'est que tous les commentaires sont un petit peu au-dessus, cachés dans les conseils.

Maintenant que vous avez eu un aperçu de « vrai » code, je dois vous avouer un truc : avec ce que vous connaissez, on peut faire bien plus court et efficace !

Peut mieux faire !

On vient de voir un code qui fonctionne. J'insiste bien là-dessus, il fonctionne. Mais il est loin d'être idéal. C'est un code que je qualifierais de simplet, il n'y a pas de réflexion, pas d'utilisation de ce qu'on a appris pour simplifier le script. Et la logique même du script est assez moyenne et naïve.

C'est pour ça que je vais vous montrer un second code : le rendu est strictement identique, mais ce second script est bien mieux !

Code PHP :

<?php

error_reporting(E_ALL);

/* Déclaration des constantes */
/* Déclaration des fonctions */
function operation($a, $b, $operation)
{
// On vérifie si l'opération est définie
if($operation >= 0 && $operation <= 4)
{
// On crée un array contenant trois des cinq opérations
// On ne peut pas mettre les deux dernières car si $b vaut zéro, on aura une erreur
$calcul = array(
$a + $b,
$a - $b,
$a * $b
);
// Si l'on veut diviser ou faire le modulo et que $b est égale à zéro, on retourne une erreur
if($b == 0 && $operation >= 3)
{
return 'Une erreur est survenue : vous ne pouvez pas diviser par zéro';
}
// Si l'on veut diviser ou faire le modulo et que $b est différente de zéro
// On complète le tableau des différents calculs possibles
if($b != 0 && $operation >= 3)
{
$calcul[] = $a / $b;
$calcul[] = $a % $b;
}
// Enfin, on retourne le résultat qui correspond à l'opération demandée !
return $calcul[$operation];
}
else
{
return 'Une erreur est survenue : opération indéfinie';
}
}
/* Traitement des données */
// On vérifie que toutes les valeurs des associations contenues dans $_POST sont remplies
$is_valid = true;
foreach($_POST as $val)
{
if(trim($val) == '')
{
$is_valid = false;
}
}
// On vérifie que le formulaire est soumis et bien rempli
if(isset($_POST['a']) && isset($_POST['b']) && isset($_POST['operation']) && $is_valid)
{
$display = true;
$result = operation((int)$_POST['a'], (int)$_POST['b'], (int)$_POST['operation']);
$error = is_string($result);
// On utilise à nouveau un array pour simplifier le traitement
// On récupère le signe qui est associé à $_POST['operation']
$signe = array(' + ', ' - ', ' * ', ' / ', ' % ');
if(!$error)
{
$signe = $signe[(int)$_POST['operation']];
}
}
else
{
$display = false;
$result = false;
$error = false;
}
/* Affichage des résultats et du formulaire */
if($display)
{
if($error)
{
$result;
}
else
{
echo (int)$_POST['a'] . $signe . (int)$_POST['b'] . ' = ' . $result;
}
}
?>
<form action="index.php" method="post">
<p>
Opérande n°1 :<input type="text" name="a" />
<br />
Opérande n°2 :<input type="text" name="b" />
<br />
Opération :
<select name="operation">
<option value="0">Addition</option>
<option value="1">Soustraction</option>
<option value="2">Multiplication</option>
<option value="3">Division</option>
<option value="4">Modulo</option>
</select>
<br />
<input type="submit" value="Calculer" />
</p>
</form>

Vous voilà confrontés à deux scripts qui font la même chose. L'un des deux est meilleur, le second. Mais pourquoi ?
Tout d'abord, la longueur. En effet, si l'on omet les commentaires, le second script est moins long que le premier.

Mais bon, si ce n'était qu'une histoire de nombre de lignes, je vous le dis tout net : ça ne sert à rien de s'embêter.

Vous constatez que les modifications sont nombreuses dans les sections concernant la déclaration des fonctions et concernant le traitement des données. En effet, l'affichage est quelque chose de relativement statique : il n'y a pas de moyen pour améliorer réellement ça. Au mieux, on peut gagner quelques microsecondes et améliorer la clarté.

C'est toujours le traitement des données qui prend le plus de temps dans un script PHP, c'est donc là-dessus que vous devez porter votre attention pour essayer d'améliorer ça.

La plus grande amélioration dans la fonction, c'est la diminution du nombre de structures conditionnelles. Dans le premier script, il y en a six, alors que dans le second il n'y en a que trois, moitié moins.
Mais en quoi est-ce utile ?
Eh bien, quand vous avez une structure conditionnelle, le PHP évalue l'expression entre les parenthèses, ce qui prend du temps. Moins d'évaluation, moins de temps perdu. C'est particulièrement vrai dans les boucles. En effet, dans les boucles, les conditions sont réévaluées à chaque fois, donc si l'on peut supprimer ne serait-ce qu'une d'entre elles, on pourrait éviter beaucoup d'évaluations inutiles.

Pour éviter de devoir faire beaucoup de conditions, vous voyez que j'ai utilisé un array. En effet, les clés de cet array vont de 0 à 4, tout comme les attributs value de mon formulaire. Je peux donc très simplement récupérer le résultat du calcul en utilisant un array et la valeur de l'attribut value.
Mais je ne pouvais pas mettre les cinq opérations tout de suite dans mon array. En effet, si je l'avais fait, j'aurais eu une erreur :

Code console :

Warning: Division by zero in C:\wamp\www\OwnBB\index.php on line 93

Cette erreur m'indique qu'à la ligne 93, j'ai divisé un nombre par zéro. Si vous rencontrez cette erreur, faites des echo et des var_dump() de vos expressions pour savoir d'où vient le problème (c'est grâce à ces deux structures / fonctions qu'on peut identifier la plupart des bogues !).

Pour la déclaration des fonctions, c'est fini. On va maintenant passer au traitement des données, qui a aussi subi un petit lifting.

La première chose qui a été modifiée, c'est la condition pour vérifier si les variables existent et ne sont pas vides. Tout d'abord, vous devez savoir une chose que je ne vous ai pas encore dévoilée : quand un formulaire est soumis (avec un bouton submit ou un bouton image), toutes les associations que peut créer ce formulaire existent. Peu importe que vous ayez rempli ou non le formulaire, tout existe dès que le formulaire est soumis. La seule exception est la case à cocher, mais ça, vous le savez déjà.

On peut donc affirmer que si le formulaire n'a pas été soumis, $_POST est un array vide, sinon c'est un array rempli avec des associations. Or, si l'on se souvient bien de nos notions de transtypage, on sait que quand on transtype un array en booléen, deux cas sont possibles :

  • si l'array est vide, le booléen vaut false ;
  • sinon, le booléen vaut true.

Maintenant, le foreach : vous savez que ça sert à parcourir un array. Ce qui est bien avec cette structure, c'est qu'elle ne génère pas d'erreur si l'array qu'on lui passe est vide.
Avant mon foreach, je crée une variable booléenne qui vaut true.
Je parcours le tableau et j'assigne à cette variable le retour de trim($val) == ''.
Cette expression peut retourner soit true, soit false. Si la variable est constituée uniquement d'espaces ou si elle est vide, ça retourne true, sinon false.
En clair, si une seule des valeurs contenues dans $_POST est vide (la chaîne vide '' ou une chaîne faite uniquement d'espaces), $is_valid vaudra false.
Je n'étais pas obligé de vous montrer cela, ça n'a pas grand intérêt ici. Mais quand vous aurez à vérifier si quarante petites zones de texte sont remplies, ça vous sera très utile.

La condition, vous devez la comprendre : on vérifie que $_POST n'est pas vide et que tous les champs sont remplis.

La deuxième grosse amélioration, c'est la suppression des cinq conditions ! On la résume en une seule grâce aux arrays pour la deuxième fois.

Ce second script est plus propre et plus efficace que le premier. Ce que je veux que vous compreniez, c'est qu'il y a toujours moyen de voir un problème sous un autre angle. Le but du jeu, c'est de trouver l'angle qui vous donnera la solution la plus performante. Cette recherche de la solution la plus efficace, on appelle ça l'optimisation.

En PHP, le meilleur moyen d'optimiser son code (qu'il soit le plus rapide possible), c'est de revoir sa logique, d'essayer de supprimer des structures coûteuses en performance (comme des conditions, des boucles, des fonctions lourdes...).

Beaucoup de gens vont vous donner des petits « trucs », comme utiliser ' à la place de " pour délimiter vos chaînes de caractères. Ce genre de « truc » n'est pas faux, c'est vrai. Mais le temps que vous gagnerez est vraiment négligeable comparé à ce que vous pourriez gagner en revoyant votre logique. C'est pour ça que je n'appelle pas ce genre de pratique de l'optimisation, mais du bricolage, du chipotage.

C'est comme si vous deviez aller de Paris à Marseille. Vous avez une 2 CV, vous demandez à votre voisin : « À ton avis, j'irais plus vite si je gonfle un peu mes pneus ? » Ça ne vous fera gagner que quelques minutes.
Alors que si vous revoyiez votre logique et que vous preniez le TGV à la place de cette voiture, vous gagneriez des dizaines d'heures.

Désormais, quand vous regarderez un script, vous devrez toujours vous demander : « Ne peut-on pas l'améliorer ? » Il ne faut pas se contenter de quelque chose qui fonctionne, il faut toujours viser la performance. Et d'ailleurs, il y a sans doute encore moyen d'améliorer ce second script.  Après tout, peut-être n'ai-je pas eu l'angle de vue qui permettrait d'améliorer encore tout ça.

Pfiou, voilà une bonne chose de faite.
Après ce TP, plusieurs cas sont possibles.

Si vous avez réussi du premier coup, félicitations, c'est très bien.
Si vous avez dû chercher un peu, ou même beaucoup, mais que vous y êtes arrivés malgré tout, je vous félicite encore plus car vous vous êtes donné du mal et vous avez persévéré.
À ceux qui auraient totalement raté le TP, ne vous en faites pas. C'est en codant qu'on devient codeur.
Pour être honnête, je n'ai jamais réussi un seul TP du tutoriel qui m'a appris les bases du PHP, et ça ne m'a pas empêché d'aller assez loin.

Si vous êtes chauds pour la partie II, qui s'annonce très amusante, que faites-vous encore là ?

 

Infos Plan Partenaires
À propos Webmasters
C.G.U Services Gratuits Annuaire de sites web
Bannières Forum Ionoa

 

Aipoweb est un site édité par ASMOH NetWork  ©

Créer un site gratuit avec e-monsite - Signaler un contenu illicite sur ce site