Up First Previous

Adapter le contenu à l'internaute
PHP & MySQL

Next Last

 Syntaxe du PHP 

PHP signifie Personal Home Page hypertext processor, c'est un langage de script qui s'exécute sur un serveur afin de construire dynamiquement des pages web. Le code PHP est intimement lié au code XHTML qu'il contribue à construire. Un script PHP s'écrit entre des balises <? et ?>, ou <% et %> (comme en ASP), ou enfin <?php et ?>. C'est le fichier de configuration du serveur qui défini quelle(s) notation(s) est(sont) possible(s). Afin de garantir une portabilité maximale, on préfèrera donc la dernière notation qui est supportée par la quasi-totalité des serveurs. D'autre part, pour indiquer au serveur qu'il doit évaluer des instructions PHP, on utilisera l'extension .php pour les fichiers à la place de .html (.php3 et .php4 ne doivent plus être utilisées).

Comme vous vous en rendrez compte ci-dessous, tout comme JavaScript, PHP ressemble fortement au langage C en terme de syntaxe et l'apprentissage de ce langage est donc très intuitive pour qui sait programmer en C/C++. Son but étant de construire dynamiquement certaines parties d'une page XHTML, il suffit uniquement de savoir écrire dans cette page à l'aide de la commande echo : echo "<p>Ceci est un paragraphe XHTML</p>";.

attention ! PHP est un langage vivant et donc il évolue. A partir de la version 5, PHP devient un langage objet et s'apparente donc plus au C++ qu'au C. Cependant, nous nous restreignons ici aux versions 4.xx de PHP qui sont encore les plus courantes, notamment chez les fournisseurs d'accès à Internet. La notion de classe reste donc encore très sommaire...

 Variables et constantes 

Une variable est caractérisée par le caractère $ puis par un nom composé de lettres, de chiffres et du caractère _ (souligné), mais un chiffre ne peut être le premier caractère du nom d'une variable. Son type est implicitement défini par la valeur qui lui est affectée. Ainsi $i=3; défini un entier (int ou integer), $_2pi=2*3.14; un flottant (float), $test=($i<5); un booléen (bool ou boolean) et $phrase="j'ai fait une string"; une chaîne de caractères (string).
Si cela vous parait nécessaire, il est possible de forcer le type en effectuant un transtypage, c'est-à-dire en plaçant le type souhaité entre parenthèses avant la valeur comme dans cet exemple : $annee="2006"; $i=(int)$annee;. Cependant il est généralement préférable de laisser PHP se débrouiller...

attention ! En PHP (contraiement au C/C++), le type d'une variable peut changer au cours du programme en fonction des valeurs qui lui sont affectées ! Ainsi, dans l'exemple suivant : $i=2; $i*=3.14;, $i est successivement un int puis un float.

Un booléen peut prendre deux valeurs : vrai (true) ou faux (false). Tout ce qui n'est pas false est true (jusque là c'est logique) et la valeur false est définie par :

  • la booléen false
  • l'entier 0 ou le flottant 0.0 (zéro)
  • la chaîne de caractères vide ("")
  • un tableau sans élément
  • le type NULL

Les chaînes de caractères sont caractérisées par des guillements simples ('une première chaîne') ou doubles ("une deuxième chaîne"). Comme il arrive nécessairement que l'on ait besoin de mettre une apostrophe dans une chaîne définie par des guillemets simples ou un guillemet dans une chaîne définie par des guillemets doubles, il est important de connaître le caractère d'échappement \ qui modifie la sémantique du caractère suivant :

  • \" et \' affichent respectivement un guillement et une apostrophe sans mettre fin à la chaîne de caractères à laquelle ils appartiennent
  • \n indique un saut de ligne
  • \t indique une tabulation horizontale
  • \r indique un retour chariot
  • \$ indique un caractère dollar
  • \\ indique un caractère backslash (\)

Si une chaîne de caractères contient le nom d'une variable, il est possible de l'utiliser pour changer sa valeur comme dans cet exemple : $mavariable=2; $chaine="mavariable"; $$chaine+=3; echo $mavariable: qui affiche la valeur 5.

Enfin il est possible de définir des constantes avec la commande define. Les constantes ne sont pas précédées du signe $ : define('PI',3.1415); $_2pi=2*PI;.

 Tableaux 

Comme en JavaScript, il existe en PHP des tableaux indexés (les cellules sont identifiées par des indices commençant à 0) et des tableaux associatifs (les cellules sont identifiées par des clefs alphanumériques). Les clefs des tableaux associatifs doivent forcément être placées entre des guillemets simples (apostrophes).

attention ! Il faut vraiment voir les tableaux comme des collections d'objets quelconques. Il n'est pas nécessaire que toutes les cellules d'un tableau soient du même type (comme cela est le cas en C/C++). Finalement, un tableau est simplement un conteneur défini par le mot réservé array et son nombre d'éléments est donné par la fonction count() comme le montre l'exemple suivant : $tab = array("abc", 3.14, false); $tab[] = 17; echo "il y a ".count($tab)." valeurs dans le tableau \$tab et \$tab[3]=${tab[3]}"; (4 valeurs et celle d'indice 3 est 17).

 Opérateurs, Boucles, Tests 

PHP est quasiment un clône de C/C++ (et donc de JavaScript) pour la syntaxe et je vous laisse donc vous reporter à l'un ou l'autre de ces cours pour plus de détails. Intéressons-nous aux différences :

  • Il est possible d'évaluer une variable contenue dans une chaîne de caractères, mais pas une constante : echo "Le double de PI vaut $_2pi"; affiche donc Le double de PI vaut 6.283 et la constante PI n'est pas évaluée. Si le nom d'une variable doit être collé à un caractère pour l'affichage, on utilise alors des accolades : $place=3; echo "je suis arrivé ${place}ème de la course".
  • La concaténation de chaînes de caractères s'effectue avec l'opérateur . (point) et non pas + comme en JavaScript. L'opérateur .= est également défini.
  • == teste l'égalité et === l'identité. Par exemple on a 2=="2" mais 2!=="2".
  • PHP est un langage interprété contrairement à C et C++ qui sont des langages compilés. Les erreurs sont donc identifiées lors de la contruction de la page XHTML correspondante et les signalements d'erreur se font donc directement dans cette page. Pour ne pas afficher les messages d'erreur, il faut faire précéder les appels de fonction du caractère @ (nous y reviendrons notamment dans la partie sur MySQL).
  • && (et logique) et || (ou logique) existent en PHP mais and, or et xor (ou exclusif) sont également définis (avec des priorités plus importantes).

 Notion de classe 

Rappelons que nous nous plaçons ici dans le cadre de PHP 4.xx et que PHP n'est donc pas encore un langage objet. Malgré tout, pour assurer une bonne lisibilité du code et surtout pour permettre la portabilité et l'évolutivité des outils que nous définirons, nous veillerons à regrouper sémantiquement le code au sein d'une classe lorsque cela a un sens.

Une classe est un ensemble de champs (données) et de méthodes (fonctions et procédures) qui permettent de manipuler ces champs. Si une classe est bien construite, un utilisateur ne doit jamais accéder directement aux champs, il ne peut les consulter et les modifier qu'au travers des méthodes proposées.

  • On définit une classe ainsi :
    class MaClasse
    {
      var $champ1 = /* valeur par défaut */;
      /* ... */
      var $champN;
      
      function MaClasse($champ1, /* ... */, $champN = /* valeur par défaut */)
      // constructeur de la classe
      {
        $this->champ1 = $champ1;
        /* ... */
        $this->champN = $champN;
      }
      
      function FonctionMembre1(/* arguments */) { /* code de la procédure */ }
      function FonctionMembre2($arg1, /* ... */, $argM) { /* code de la fonction*/ return /* valeur de retour */; }
      /* ... */
    }
  • On déclare une instance de classe (variable, objet) ainsi : $obj = new MaClasse(/* arguments */);

attention ! Pensez à faire précéder la déclaration des champs du mot réservé var !

 Lecture et écriture de fichiers 

Voici quelques commandes de base de gestion de fichiers (similaires aux commandes de fichiers en C) :

  • Pour lire un fichier :
    if (file_exists("rep/fichier.txt"))
    {
      if (! ($fp=fopen("rep/fichier.txt", "r"))) // ouvrir le fichier en lecture
        exit;                                    // arrêter si l'ouverture a échouée
      while (! feof($fp))                        // tant qu'on n'a pas atteint la fin du fichier
      {
        if (! fscanf($fp,"%d",$nb))              // on lit un entier et le place dans la variable $nb
          /* ... */                              // en cas d'erreur de lecture, ...
        /* ... */                                // en toute logique, ici on utilise $nb ... 
      }
      fclose($fp);                               // penser à fermer le fichier !!
    }
  • Pour écrire un fichier :
    if (! ($fp=fopen("rep/fichier.txt", "w")))   // ouvrir le fichier en écriture
        exit;                                    // arrêter si l'ouverture a échouée
      fwrite($fp,$nb);                           // on écrit le contenu de la variable $nb
      /* ... */
      fclose($fp);                               // penser à fermer le fichier !!
  • Pour se placer à un endroit précis du fichier : fseek($fp, 0); (0 pour le début)
  • On peut poser/lever un verrou sur un fichier ouvert pour interdire une autre ouverture en parallèle. Pour cela, on utilise :
    flock($fp, LOCK_EX); // pose un verrou exclusif
    flock($fp, LOCK_UN); // libère le verrou

 Fonctionnalités avancées de PHP 

Il existe de très nombreuses fonctionnalités qui ont ajoutées à PHP pour manipuler des images, tracer des graphes, ... Leur présentation est hors du cadre de ce cours et je vous laisse donc vous reporter aux liens proposés en bas de page pour plus d'informations.

 Gestion des formulaires XHTML 

Maintenant que nous avons fait un rapide tour d'horizon de PHP, nous pouvons en arriver à la gestion des formulaires XHTML qui est sans doute la première raison qui vous a donné envie de découvrir PHP. Pour l'instant, nous allons nous contenter de récupérer et d'utiliser des valeurs transmises depuis un formulaire par la méthode post :

  • les données reçues par la page sont stockées dans le tableau global $_POST ($HTTP_POST_VARS n'est plus utilisé). Ainsi, un champ nom du formulaire appellant cette page à sa valeur stockée dans la case $_POST['nom'].
  • Par exemple, on écrira :
    echo "<p>votre nom est : ${_POST['nom']}</p>\n";\n permet d'écrire un saut de ligne et les accolades indiquent que le nom de la variable qui doit être évaluée est _POST['nom'] et pas juste _POST (nous reviendrons sur ces notions en détail).
  • On peut déclarer un tableau associatif ainsi :
    $tab = new array("clef1" => "valeur1", ..., "clefN" => "valeurN");
    puis faire une boucle sur ces valeurs ainsi :
    foreach($tab as $clef => $valeur) { /* corps de la boucle */ }
    à chaque itération de la boucle, les variables $clef et $valeur sont définies.

 Syntaxe du MySQL 

Le but n'est pas ici de proposer un tour d'horizon complet de MySQL ou d'autres bases de données (BdD). Seuls sont présentés les outils de base permettant de construire et de gérer une base de données MySQL simple en PHP. Dans toute la suite, nous utiliserons les dénominations suivantes :

  • Base de données : ensemble de tables
  • Table : ensemble d'enregistrements découpés en colonnes de types fixés
  • Colonne : unité de connaissance d'une table, de type prédéfini
  • Enregistrement : une instance des colonnes d'une table définissant une relation de la base de données
  • Requête : interrogation de la base de données pour créer, consulter, ou détruire des tables, des colonnes ou des enregistrements

Par exemple, une table MembreSite peut être décomposée en colonnes Nom, Prénom, Login, Email et Url et contenir les enregistrements suivants :

  • Duchemin, Raoul, rduchemin, rduchemin@fai.fr, www.rduchemin.net
  • Smith, Émile, mimile, mimile@fai2.fr, www.mimile.com
  • ...

 Connexion/Déconnexion à une BdD MySQL en PHP 

Comme pour lire ou écrire dans un fichier, il faut ouvrir une base de données avant de l'utiliser puis la fermer lorsqu'on a fini d'effectuer des requêtes.

On utilise la fonction id = mysql_connect($server, $login, $pwd); pour se connecter au serveur MySQL d'adresse $server (ici stockée dans une variable PHP) en s'identifiant avec $login et $pwd.
Pour une utilisatin en local avec Easy-PHP, on a par défaut $server='localhost', $login='root' et $pwd=''.
Pour utiliser le serveur d'un fournisseur d'accès à Internet (FAI), généralement les login et mot de passe sont ceux du compte client.

attention ! Vous verrez souvent les commandes MySQL précédées d'un caractère @. Ceci permet de passer en mode silencieux et interdit l'affichage des éventuelles erreurs relatives à l'exécution de cette commande. Le but est de ne pas donner d'informations sur l'architecture de la base de données afin d'empêcher tout piratage. Généralement, on utilise donc des commandes sans @ le temps de debugger puis on ajoute cette sécurité lorsque l'on utilise les outils définis.

La valeur de retour id permet de tester (sans affichage) si la connexion a pu se faire normalement : if (! $id) exit; /* ERREUR */. Elle permet également de fermer la connexion à l'aide de la commande : @mysql_close($id);

 Création/Sélection d'une BdD MySQL en PHP 

Une fois que l'on est connecté au serveur, il reste encore à préciser quelle base de données on souhaite utiliser. Pour cela, on écrit if (! @mysql_select_db($dbname)) exit; où $dbname est le nom de la base de données. Chez les FAI, généralement on a $dbname=$login et il n'est donc possible de n'utiliser qu'une seule base de données (mais le nombre de tables n'est pas restreint et c'est surtout cela qui est important).

Pour créer une base de données (impossible chez les FAI), on utilise la commande if (! @mysql_create_db($dbname)) exit;.

 Effectuer une requête MySQL en PHP 

Si la variable PHP $sql contient une requête MySQL, on interroge la base de données à l'aide de la commande if (!($query=@mysql_query($sql))) return null;. La variable $query contient alors les résultats que l'on peut parcourir avec la commande mysql_fetch_array qui retourne pour chaque ligne de résultat un tableau indexé ou associatif . En pratique, on écrit donc souvent des boucles du type :
while($row = @mysql_fetch_array($query))
  /* commande utilisant $row[0], $row[1], ... ou $row['Nom'], $row['Prenom'], ... */
@mysql_free_result($query);

La commande mysql_free_result libère la mémoire du serveur de la base de données occupée par le résultat de la requête.

 Plus de commandes MySQL en PHP 

Nous ne verrons pas d'autres commandes PHP permettant d'interagir avec la base de données MySQL. Pour plus d'informations, je vous laisse vous reporter (par exemple) au site php.net ; la liste des commandes est donnée en bas de page et pour chacune d'elles de bons exemples sont présentés.

 Enfin du MySQL 

Bon, jusqu'ici on a vu tout l'enrobage mais le plus important reste malgré tout les commandes MySQL que l'on peut mettre dans la variable $sql transmise lors de l'appel de mysql_query.

Les principales commandes MySQL sont :

  • CREATE : pour créer une table
    CREATE TABLE matable(nom_colonne type, ...)
  • DROP : pour destruire des tables
    DROP TABLE matable1 matable2
  • DELETE : pour effacer des données
    DELETE FROM matable ...
  • INSERT : pour ajouter un enregistrement
    INSERT INTO matable VALUES (valcol1, valcom2, ...)
  • SELECT : pour rechercher des données
    SELECT nom_colonne FROM matable [...]
  • UPDATE : pour modifier des données
    UPDATE matable SET nomcol1='newval1', ...

Il existe des clauses qui permettent de mieux préciser les requêtes que l'on effectue :

  • WHERE : pour restreindre le champ d'application
    ... WHERE nomcol1='val1' AND nomcol2 BETWEEN 'val2min' AND 'val2max' ...
  • ORDER BY : pour trier les résultats
    ... ORDER BY nomcol ...
  • ... : en travaux
    ... ??? ...

Enfin il existe des fonctions utilisables dans les requêtes :

  • COUNT : calcule le nombre de valeurs
  • AVG : calcule la moyenne
  • ... : en travaux

en travaux !Je m'excuse mais je n'ai pas eu le temps de rédiger cette partie en détail et je vous laisse donc pour le moment vous reporter à ce cours et à ce site pour plus d'explications.

 Bibliothèque de gestion de base de données 

Puisque notre but n'est pas ici de devenir des professionnels de MySQL, il est inutile de se forcer à trop apprendre les commandes MySQL et les commandes PHP d'interaction avec le serveur MySQL. Dans une vue à moyen terme d'utilisation d'une version PHP véritablement objet (rappelons que de nombreux FAI ne fournisse encore que du PHP4), nous pouvons nous contenter de définir et d'utiliser une classe PHP de manipulation de MySQL offrant des outils de haut niveau afin de simplifier notre tâche. Je vous propose comme base la classe BaseDeDonnees définie dans le fichier bdd.inc.php (bouton droit, enregistrer la cible du lien sous...)

J'espère qu'elle est suffisament documentée pour être compréhensible...

 Utilisation de PHP-MyAdmin 

en travaux, mais c'est assez intuitif puisque graphique...

 Exercices pratiques sur PHP 

  1. Finissons-en avec le traitement de formulaires :
    • Télécharger les fichiers renseignements_1.php et renseignements_2.php et compléter leurs parties PHP pour maintenir la cohérence lors de la saisie des informations (les détails sont donnés en commentaire).
    • Ecrire une page inscription.php qui sauvegarde les données saisies dans un fichier login.datlogin est le nom d'utilisateur saisi sur renseignements_1.php.
    • Modifier la fonction de validation du formulaire de renseignements_1.php afin de vérifier que le login choisi n'est pas déjà utilisé (relire la question précédente pour trouver comment faire).
    • Ecrire une page donnees.php qui, selon la valeur d'une variable droits qui peut être public ou privé, affiche tout ou partie des données d'un utilisateur dont le login est donné dans une variable login.
      A terme, les valeurs de ces deux variables seront lues dans une base de données MySQL...
    Correction : renseignements_1.php, renseignements_2.php, inscription.php, renseignements_1bis.php, donnees.php.
  2. Comment simplifier l'écriture et la modification des pages d'un site complet ? Simplement en définissant des classes génériques qui permettent d'automatiser les traitements les plus courants au nombre desquels on compte la structure d'une page XHTML.
    Ecrire un script xhtml_page.inc.php décrivant une classe XHTML_page comprenant les champs width, title, author, webmastermail, mailsubject, webmastermailtotext et wwwdir. Tous ces champs seront initialisés par le constructeur de la classe.
    Les autres fonctions membres de la classe qui doivent être écrites sont :
    • Get_wwwdir() : renvoit le champ wwwdir.
    • Get_width() : renvoit le champ width.
    • Get_title() : renvoit le champ title.
    • Get_author() : renvoit le champ author.
    • Header_XHTML_code() : écrit le début du code XHTML d'une page (en utilisant les champs author, title et wwwdir pour charger le script standards.js).
    • Header_Body_XHTML_code() : écrit la fin de la partie head et le début de la partie body (notamment la définition d'un calque invisible définissant une ancre de nom haut).
    • FooterDiv_XHTML_code() : écrit un calque d'identifiant footer possédant une ancre de nom bas et dans un tableau un lien vers le haut de la page, un autre vers le courriel du webmestre et la date de dernière modification (document.lastModified en JavaScript).
    • Footer_XHTML_code() : écrit la fin du code XHTML d'une page.
    Correction : xhtml_page.inc.php.
  3. Afin de tester le script précédent, écrire une page PHP nommée hello_world_auto.php dont le contenu est simplement un calque d'identifiant contenu contenant un paragraphe de texte Hello World. Ajouter ensuite à la classe XHTML_page des fonctions renvoyant une chaîne de caractères décrivant les styles de base suivants :
    • Page_CSS_screen_code() : styles de base pour l'écran.
    • Page_CSS_print_code() : styles de base pour l'imprimante.
    • FooterDiv_CSS_screen_code() : styles de base du calque de pied de page pour l'écran.
    • FooterDiv_CSS_print_code() : styles de base du calque de pied de page pour l'imprimante.
    Pour cela, on utilisera le champ width de la classe et on fera en sorte de définir un cadre tout autour du document, un trait de même épaisseur séparant les calques contenu et footer. Pour le reste, faites comme bon vous semble...
    Correction : hello_world_auto.php, xhtml_page_css.inc.php, hello_world_auto_css.php.
  4. Toujours pour automatiser la création de sites, intéressons-nous à la gestion de menus dynamiques.
    Ecrire un script menu.inc.php définissant une classe Menu qui doit remplir les fonctions suivantes :
    • XHTML_code() : création du menu à partir des valeurs des champs de la classe.
    • CSS_screen_code() : styles de base pour l'écran.
    • CSS_print_code() : styles de base pour l'imprimante.
    En pratique, tout le problème consiste à déterminer les données nécessaires à la réalisation d'un menu générique.
    Correction : menu.inc.php.

 Exercices pratiques sur MySQL 

  1. En utilisant la classe BaseDeDonnees proposée plus haut, créer la table MembreSite présentée au début du cours sur MySQL et remplissez la avec 5 enregistrements. Faites ensuite en PHP une liste affichant toutes les données de tous les membres (SELECT * FROM MembreSite).

 Liens et bibliographie