PHP
Étape 7: Un peu de style SVP

Étape 7: Un peu de style SVP

Introduction

Maintenant que notre site Web dynamique est opérationnel du point de vue des fonctionnalités, il nous reste la partie “habillage” pour le rendre plus “sympathique” visuellement. S’il y a (trèèèèèsssss) longtemps la mise en page se faisait directement en HTML en jouant sur les options des différentes balises, il est maintenant d’usage de dissocier le contenu (structuration des données) de la forme (comment afficher ces données). C’est l’objectif de la techno CSS:

  • les données à afficher sont structurées en HTML
  • la manière dont elles doivent être affichées (mise en page) est codée en CSS

CSS

Les feuilles de style en cascade, généralement appelées CSS (de l’anglais Cascading Style Sheets), sont un langage informatique permettant de décrire la présentation des documents HTML (cf. Wikipédia). L’objectif est de “sortir” la mise en forme du code HTML, lequel se contente de “structurer” les données.

Alors autant vous le dire tout de suite, je ne suis pas un pro du CSS. Et je connais beaucoup d’autres moyens pour m’amuser en informatique et en programmation que de faire du CSS… ☺ Mais bon, cette techno est incontournable sur le Web, donc autant comprendre, au moins d’un point de vue technique, comment elle s’intègre à tout ce que l’on a déjà vu jusqu’ici.

Style des balises HTML standard

Quand on débute en CSS, le plus simple est de commencer par redéfinir le style d’affichage pour les balises HTML classiques.

Je commence par changer le style du body: fond beige (couleur PapayaWhip) et police de caractères en Verdana. Ce qui nous donne le code CSS suivant:

body {
  background-color: PapayaWhip; 
  font-family: Verdana, sans-serif; 
  font-size: 100%;
}

Je modifie ensuite la manière dont les titres en h1 seront affichés: centrés dans la fenêtre, en couleur OliveDrab et en taille de caractère 200% par rapport à la taille héritée du body. Ce qui nous donne le code CSS suivant:

h1 {
  font-size: 200%; 
  color: OliveDrab; 
  text-align: center;
}

Où placer ces définitions ? Là, il y a 2 possiblités:

  1. soit directement dans le code HTML dans le header entre 2 balises <style> et </style>
  2. soit dans un fichier CSS séparé avec un lien dans le header de la page HTML

Si le code du style est très court, la solution 1 peut être envisagée sans trop “polluer” le code HTML. Mais dès que le CSS va prendre de l’ampleur, la solution 2 est clairement la plus adaptée en dissociant le code HTML et le style CSS.

Nous créons donc un fichier style12a.css contenant le code CSS suivant:

body {
    background-color: PapayaWhip; 
    font-family: Verdana, sans-serif; 
    font-size: 100%;
}

h1 {
    font-size: 200%; 
    color: OliveDrab; 
    text-align: center;
}

Dans notre fichier HTML nous intégrons un lien vers cette feuille de style via une balise <link> dans le header:

<html>

  <head>
    <meta charset="utf-8"/>
    <title>Gestion des emplois du temps</title>
    <link href="style12a.css" rel="stylesheet" media="all" type="text/css"> 
  </head>

  <body>
  ...

Et voilà le résultat sur la copie d’écran ci-dessous, avec le lien ici pour tester par vous-mêmes. Ça commence déjà à être plus joli ☺

php_step07_index12a
Page HTML avec PHP, SQL, JavaScript et CSS

Code source du formulaire HTML avec PHP, SQL, JavaScript et CSS (fichier <code>index12a.php</code>)
<html>

  <head>
    <meta charset="utf-8"/>
    <title>Gestion des emplois du temps</title>

    <link href="style12a.css" rel="stylesheet" media="all" type="text/css"> 

    <script language="javascript">
      function verifier() {
        var dmin = document.myform.datemin.value;
        var hmin = document.myform.heuremin.value;
        var dmax = document.myform.datemax.value;
        var hmax = document.myform.heuremax.value;

        var ddebut = new Date(dmin+'T'+hmin)
        var dfin   = new Date(dmax+'T'+hmax)

        if (ddebut<dfin) {
          document.myform.msgerreur.value = "";
          return true;
        } else {
          document.myform.msgerreur.value = "ERREUR";
          return false;
        }
      }
    </script>
  </head>

  <body>
    <?php
      // Ouverture du connecteur à la BdD une fois pour toute au début du script
      $dbh = new PDO('sqlite:planning.db') or die("impossible d'ouvrir la base sqlite");
      $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      // Récupération des paramètres CGI éventuels
      // NB: si la valeur est 'none' alors le paramètre est ignoré
      if (array_key_exists('cours',$_GET)) {
        if ($_GET['cours'] != 'none') {
          $cours = $_GET['cours'];
        }
      }
      if (array_key_exists('salle',$_GET)) {
        if ($_GET['salle'] != 'none') {
          $salle = $_GET['salle'];
        }
      }
      if (array_key_exists('prof',$_GET)) {
        if ($_GET['prof'] != 'none') {
          $prof = $_GET['prof'];
        }
      }
      if (array_key_exists('datemin',$_GET)) {
        if ($_GET['datemin'] != '') {
          $datemin = $_GET['datemin'];
        }
      }
      if (array_key_exists('datemax',$_GET)) {
        if ($_GET['datemax'] != '') {
          $datemax = $_GET['datemax'];
        }
      }
      if (array_key_exists('heuremin',$_GET)) {
        if ($_GET['heuremin'] != '') {
          $heuremin = $_GET['heuremin'];
        }
      }
      if (array_key_exists('heuremax',$_GET)) {
        if ($_GET['heuremax'] != '') {
          $heuremax = $_GET['heuremax'];
        }
      }
    ?>

    <h1>Gestion des emplois du temps</h1>

    <form name="myform" action="index12a.php" method="GET" onsubmit="return verifier()">
      <!-- Choix date et heure minimum -->
      Date min
      <input type="date" name="datemin" <?php if (isset($datemin)) { echo 'value="'.$datemin.'"'; }?> >
      &nbsp;
      Heure min
      <input type="time" name="heuremin" <?php if (isset($heuremin)) { echo 'value="'.$heuremin.'"'; }?> >
      <br>

      <!-- Choix date et heure maximum -->
      Date max
      <input type="date" name="datemax" <?php if (isset($datemax)) { echo 'value="'.$datemax.'"'; }?> >
      &nbsp;
      Heure max
      <input type="time" name="heuremax" <?php if (isset($heuremax)) { echo 'value="'.$heuremax.'"'; }?> >
      &nbsp;
      <input type="text" name="msgerreur" value="" disabled>
      <br>

      <!-- Choix du cours -->
      Nom du cours
      <select name="cours">
        <option value="none" selected>&#x3008;aucun&#x3009;</option>

        <?php
          $sql = "select * from cours;";
          foreach ($dbh->query($sql) as $row) {
            echo '<option value="'.$row['numcours'].'"';

            // S'il s'agit du cours dont l'id est dans le paramètre CGI cours, alors
            // on ajoute l'option "selected" à cet élément de la liste
            if (isset($cours)) {
              if ($cours == $row['numcours']) {
                echo ' selected';
              }
            }

            echo '>'.$row['idcours'].' ('.$row['libcours'].')</option>';
          }
        ?>
      </select>
      <br>

      <!-- Choix de la salle -->
      Nom de la salle
      <select name="salle">
        <option value="none" selected>&#x3008;aucun&#x3009;</option>

        <?php
          $sql = "select * from salle;";
          foreach ($dbh->query($sql) as $row) {
            echo '<option value="'.$row['numsalle'].'"';

            // S'il s'agit de la salle dont l'id est dans le paramètre CGI salle, alors
            // on ajoute l'option "selected" à cet élément de la liste
            if (isset($salle)) {
              if ($salle == $row['numsalle']) {
                echo ' selected';
              }
            }

            echo '>'.$row['descsalle'].'</option>';
          }
        ?>
      </select>
      <br>

      <!-- Choix du prof -->
      Nom du prof
      <select name="prof">
        <option value="none" selected>&#x3008;aucun&#x3009;</option>

        <?php
          $sql = "select * from prof;";
          foreach ($dbh->query($sql) as $row) {
            echo '<option value="'.$row['numprof'].'"';

            // S'il s'agit de l'enseignant dont l'id est dans le paramètre CGI prof, alors
            // on ajoute l'option "selected" à cet élément de la liste
            if (isset($prof)) {
              if ($prof == $row['numprof']) {
                echo ' selected';
              }
            }

            echo '>'.$row['nomprof'].'</option>';
          }
        ?>
      </select>
      <br>

      <!-- Bouton de soumission du formulaire -->
      <input type="submit" name="go" value="Rafraîchir">
    </form>

    <hr>

    <?php
      // Dans la requête SQL, on mettra un '?' à chaque endroit où l'on voudra insérer un paramètre
      $sql = "select * from planning ".
          "inner join cours on cours.numcours = planning.numcours ".
          "inner join salle on salle.numsalle = planning.numsalle ".
          "inner join prof on prof.numprof = planning.numprof ".
          "where ( (1=1)";
      $params = array();

      // Si un critère de filtre (ex: variable $prof) existe, alors on ajoute une conjonction à la clause "where"
      // dans la requête SQL et on ajoute la valeur à la liste des paramètres pour l'exécution du statement
      if (isset($cours)) {
        $sql .= " and (planning.numcours=?)";
        array_push($params, $cours);
      }
      if (isset($salle)) {
        $sql .= " and (planning.numsalle=?)";
        array_push($params, $salle);
      }
      if (isset($prof)) {
        $sql .= " and (planning.numprof=?)";
        array_push($params, $prof);
      }

      if (isset($datemin) && isset($heuremin)) {
        $dhmin = $datemin.' '.$heuremin;
        $sql .= " and (?<=datetime(debut))";
        array_push($params, $dhmin);
      } else {
        if (isset($datemin)) {
          $sql .= " and (?<=date(debut))";
          array_push($params, $datemin);
        }
        if (isset($heuremin)) {
          $sql .= " and (?<=time(debut))";
          array_push($params, $heuremin);
        }
      }

      if (isset($datemax) && isset($heuremax)) {
        $dhmax = $datemax.' '.$heuremax;
        $sql .= " and (datetime(fin)<=?)";
        array_push($params, $dhmax);
      } else {
        if (isset($datemax)) {
          $sql .= " and (date(fin)<=?)";
          array_push($params, $datemax);
        }
        if (isset($heuremax)) {
          $sql .= " and (time(fin)<=?)";
          array_push($params, $heuremax);
        }
      }

      //echo '$sql = "'.$sql.'"<br>';

      // On termine proprement notre requête SQL
      $sql .= ") order by debut;";

      // Préparation du statement avec la requête SQL
      $stmt = $dbh->prepare($sql);

      // Exécution du statement avec les paramètres indiqués dans le tableau
      $stmt->execute($params);

      // Récupération du résultat de la requête
      $res  = $stmt->fetchAll();

      echo '<table border="1">';
      echo '<tr><th>num</th><th>début</th><th>fin</th><th>cours</th><th>salle</th><th>prof</th></tr>';
      // Parcours du résultat
      foreach ($res as $row) {
        echo '<tr>';
        echo '<td>'.$row['numcreneau'].'</td>';
        echo '<td>'.$row['debut'].'</td>';
        echo '<td>'.$row['fin'].'</td>';
        echo '<td>'.'<a href="" title="'.$row['libcours'].'">'.$row['idcours'].'</a>'.'</td>';
        echo '<td>'.$row['descsalle'].'</td>';
        echo '<td>'.'<a href="infos_prof01.php?prof='.urlencode($row['numprof']).'" title="infos prof #'.$row['numprof'].'">'.$row['nomprof'].'</a>'.'</td>';
        echo '</tr>';
      }
      echo '</table>';
    ?>

    <hr>
    Copyright © 2022 Manuel Munier
    <br>
    <a href="https://munier.perso.univ-pau.fr/">https://munier.perso.univ-pau.fr/</a>

  </body>

</html>

Il est aussi possible de modifier l’affichage du tableau en personnalisant le style des balises <th>, <tr>, etc. Il est même possible d’avoir un style différent selon qu’il s’agit d’une ligne paire ou impaire. Les seules limites sont celles de votre imagination… Cliquez ici pour voir ce que donne le code CSS ci-dessous sur le tableau de notre planning.

th {
    background: dodgerblue;
    color: white;
}
tr:nth-child(even) {background: lightblue}
tr:nth-child(odd) {background: whitesmoke}

php_step07_index12b_v1
Page HTML avec PHP, SQL, JavaScript et CSS

Style pour des groupes d’éléments

Au-delà des balises natives d’HTML pour structurer le document, il est possible de définir des groupes d’éléments particuliers auxquels nous voulons appliquer tel ou tel style. C’est le rôle des balises <span> et <div>. Bien que de fonctionnement très proche, ces 2 balises ont des utilisations différentes:

  • l’élément <span> va travailler au niveau du caractère en quelque sorte; c’est un élément neutre, c’est-à-dire qu’il n’ajoute rien au document en lui-même; CSS va utiliser l’élément <span> pour ajouter des caractéristiques de style à des parties spécifiques du texte d’un document
  • l’élément <div> va travailler en termes de blocs (regroupement d’éléments); entre autres particularités, CSS pourra spécifier où placer ce bloc sur la page, indépendamment de l’endroit où il est déclaré dans le document HTML

Dans notre tableau des créneaux du planning, nous pouvons par exemple changer le style des dates de début et de fin en leur définissant un style particulier. Dans le CSS nous allons pour cela déclarer une classe mydate.

.mydate {
    color: navy;
    font-family: Arial;
    font-weight: bold;
}

Dans notre script PHP qui génère la page il nous suffira ensuite d’encadrer le texte auquel nous voudrons appliquer ce style par les balises <span class="mydate"> et </span>.

echo '<td>'.'<span class="mydate">'.$row['debut'].'</span>'.'</td>';
echo '<td>'.'<span class="mydate">'.$row['fin'].'</span>'.'</td>';

Nous allons maintenant spécifier des directives de style pour notre formulaire HTML.

.myframe {
    background-color: tan;
    border-style: inset;
    padding: 5px;
}

Dans le code HTML il suffira ensuite d’encadrer notre formulaire par les balises <div class="myframe"> et </div>.

<div class="myframe">
  <form name="myform" action="index12a.php" method="GET" onsubmit="return verifier()">
  ...
  </form>
</div>

php_step07_index12b_v2
Page HTML avec PHP, SQL, JavaScript et CSS

Code source du fichier CSS (fichier <code>style12b.css</code>)
body {
    background-color: PapayaWhip; 
    font-family: Verdana, sans-serif; 
    font-size: 100%;
}

h1 {
    font-size: 200%; 
    color: OliveDrab; 
    text-align: center;
}
 
th {
    background: dodgerblue;
    color: white;
}
tr:nth-child(even) {background: lightblue}
tr:nth-child(odd) {background: whitesmoke}

.mydate {
    color: navy;
    font-family: Arial;
    font-weight: bold;
}

.myframe {
    background-color: tan;
    border-style: inset;
    padding: 5px;
}
Code source du formulaire HTML avec PHP, SQL, JavaScript et balises CSS (fichier <code>index12b.php</code>)
<html>

  <head>
    <meta charset="utf-8"/>
    <title>Gestion des emplois du temps</title>

    <link href="style12b.css" rel="stylesheet" media="all" type="text/css"> 

    <script language="javascript">
      function verifier() {
        var dmin = document.myform.datemin.value;
        var hmin = document.myform.heuremin.value;
        var dmax = document.myform.datemax.value;
        var hmax = document.myform.heuremax.value;

        var ddebut = new Date(dmin+'T'+hmin)
        var dfin   = new Date(dmax+'T'+hmax)

        if (ddebut<dfin) {
          document.myform.msgerreur.value = "";
          return true;
        } else {
          document.myform.msgerreur.value = "ERREUR";
          return false;
        }
      }
    </script>
  </head>

  <body>
    <?php
      // Ouverture du connecteur à la BdD une fois pour toute au début du script
      $dbh = new PDO('sqlite:planning.db') or die("impossible d'ouvrir la base sqlite");
      $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      // Récupération des paramètres CGI éventuels
      // NB: si la valeur est 'none' alors le paramètre est ignoré
      if (array_key_exists('cours',$_GET)) {
        if ($_GET['cours'] != 'none') {
          $cours = $_GET['cours'];
        }
      }
      if (array_key_exists('salle',$_GET)) {
        if ($_GET['salle'] != 'none') {
          $salle = $_GET['salle'];
        }
      }
      if (array_key_exists('prof',$_GET)) {
        if ($_GET['prof'] != 'none') {
          $prof = $_GET['prof'];
        }
      }
      if (array_key_exists('datemin',$_GET)) {
        if ($_GET['datemin'] != '') {
          $datemin = $_GET['datemin'];
        }
      }
      if (array_key_exists('datemax',$_GET)) {
        if ($_GET['datemax'] != '') {
          $datemax = $_GET['datemax'];
        }
      }
      if (array_key_exists('heuremin',$_GET)) {
        if ($_GET['heuremin'] != '') {
          $heuremin = $_GET['heuremin'];
        }
      }
      if (array_key_exists('heuremax',$_GET)) {
        if ($_GET['heuremax'] != '') {
          $heuremax = $_GET['heuremax'];
        }
      }
    ?>

    <h1>Gestion des emplois du temps</h1>

    <div class="myframe">
      <form name="myform" action="index12a.php" method="GET" onsubmit="return verifier()">
        <!-- Choix date et heure minimum -->
        Date min
        <input type="date" name="datemin" <?php if (isset($datemin)) { echo 'value="'.$datemin.'"'; }?> >
        &nbsp;
        Heure min
        <input type="time" name="heuremin" <?php if (isset($heuremin)) { echo 'value="'.$heuremin.'"'; }?> >
        <br>

        <!-- Choix date et heure maximum -->
        Date max
        <input type="date" name="datemax" <?php if (isset($datemax)) { echo 'value="'.$datemax.'"'; }?> >
        &nbsp;
        Heure max
        <input type="time" name="heuremax" <?php if (isset($heuremax)) { echo 'value="'.$heuremax.'"'; }?> >
        &nbsp;
        <input type="text" name="msgerreur" value="" disabled>
        <br>

        <!-- Choix du cours -->
        Nom du cours
        <select name="cours">
          <option value="none" selected>&#x3008;aucun&#x3009;</option>

          <?php
            $sql = "select * from cours;";
            foreach ($dbh->query($sql) as $row) {
              echo '<option value="'.$row['numcours'].'"';

              // S'il s'agit du cours dont l'id est dans le paramètre CGI cours, alors
              // on ajoute l'option "selected" à cet élément de la liste
              if (isset($cours)) {
                if ($cours == $row['numcours']) {
                  echo ' selected';
                }
              }

              echo '>'.$row['idcours'].' ('.$row['libcours'].')</option>';
            }
          ?>
        </select>
        <br>

        <!-- Choix de la salle -->
        Nom de la salle
        <select name="salle">
          <option value="none" selected>&#x3008;aucun&#x3009;</option>

          <?php
            $sql = "select * from salle;";
            foreach ($dbh->query($sql) as $row) {
              echo '<option value="'.$row['numsalle'].'"';

              // S'il s'agit de la salle dont l'id est dans le paramètre CGI salle, alors
              // on ajoute l'option "selected" à cet élément de la liste
              if (isset($salle)) {
                if ($salle == $row['numsalle']) {
                  echo ' selected';
                }
              }

              echo '>'.$row['descsalle'].'</option>';
            }
          ?>
        </select>
        <br>

        <!-- Choix du prof -->
        Nom du prof
        <select name="prof">
          <option value="none" selected>&#x3008;aucun&#x3009;</option>

          <?php
            $sql = "select * from prof;";
            foreach ($dbh->query($sql) as $row) {
              echo '<option value="'.$row['numprof'].'"';

              // S'il s'agit de l'enseignant dont l'id est dans le paramètre CGI prof, alors
              // on ajoute l'option "selected" à cet élément de la liste
              if (isset($prof)) {
                if ($prof == $row['numprof']) {
                  echo ' selected';
                }
              }

              echo '>'.$row['nomprof'].'</option>';
            }
          ?>
        </select>
        <br>

        <!-- Bouton de soumission du formulaire -->
        <input type="submit" name="go" value="Rafraîchir">
      </form>
    </div>

    <hr>

    <?php
      // Dans la requête SQL, on mettra un '?' à chaque endroit où l'on voudra insérer un paramètre
      $sql = "select * from planning ".
          "inner join cours on cours.numcours = planning.numcours ".
          "inner join salle on salle.numsalle = planning.numsalle ".
          "inner join prof on prof.numprof = planning.numprof ".
          "where ( (1=1)";
      $params = array();

      // Si un critère de filtre (ex: variable $prof) existe, alors on ajoute une conjonction à la clause "where"
      // dans la requête SQL et on ajoute la valeur à la liste des paramètres pour l'exécution du statement
      if (isset($cours)) {
        $sql .= " and (planning.numcours=?)";
        array_push($params, $cours);
      }
      if (isset($salle)) {
        $sql .= " and (planning.numsalle=?)";
        array_push($params, $salle);
      }
      if (isset($prof)) {
        $sql .= " and (planning.numprof=?)";
        array_push($params, $prof);
      }

      if (isset($datemin) && isset($heuremin)) {
        $dhmin = $datemin.' '.$heuremin;
        $sql .= " and (?<=datetime(debut))";
        array_push($params, $dhmin);
      } else {
        if (isset($datemin)) {
          $sql .= " and (?<=date(debut))";
          array_push($params, $datemin);
        }
        if (isset($heuremin)) {
          $sql .= " and (?<=time(debut))";
          array_push($params, $heuremin);
        }
      }

      if (isset($datemax) && isset($heuremax)) {
        $dhmax = $datemax.' '.$heuremax;
        $sql .= " and (datetime(fin)<=?)";
        array_push($params, $dhmax);
      } else {
        if (isset($datemax)) {
          $sql .= " and (date(fin)<=?)";
          array_push($params, $datemax);
        }
        if (isset($heuremax)) {
          $sql .= " and (time(fin)<=?)";
          array_push($params, $heuremax);
        }
      }

      //echo '$sql = "'.$sql.'"<br>';

      // On termine proprement notre requête SQL
      $sql .= ") order by debut;";

      // Préparation du statement avec la requête SQL
      $stmt = $dbh->prepare($sql);

      // Exécution du statement avec les paramètres indiqués dans le tableau
      $stmt->execute($params);

      // Récupération du résultat de la requête
      $res  = $stmt->fetchAll();

      echo '<table border="1">';
      echo '<tr><th>num</th><th>début</th><th>fin</th><th>cours</th><th>salle</th><th>prof</th></tr>';
      // Parcours du résultat
      foreach ($res as $row) {
        echo '<tr>';
        echo '<td>'.$row['numcreneau'].'</td>';
        echo '<td>'.'<span class="mydate">'.$row['debut'].'</span>'.'</td>';
        echo '<td>'.'<span class="mydate">'.$row['fin'].'</span>'.'</td>';
        echo '<td>'.'<a href="" title="'.$row['libcours'].'">'.$row['idcours'].'</a>'.'</td>';
        echo '<td>'.$row['descsalle'].'</td>';
        echo '<td>'.'<a href="infos_prof01.php?prof='.urlencode($row['numprof']).'" title="infos prof #'.$row['numprof'].'">'.$row['nomprof'].'</a>'.'</td>';
        echo '</tr>';
      }
      echo '</table>';
    ?>

    <hr>
    Copyright © 2022 Manuel Munier
    <br>
    <a href="https://munier.perso.univ-pau.fr/">https://munier.perso.univ-pau.fr/</a>

  </body>

</html>

Avant / après

Je ne m’aventure pas plus loin dans le domaine du CSS car ce n’est pas l’objet de ce tutoriel ☺ Je voulais simplement vous montrer, d’un point de vue purement technique, comment faire le lien entre le code HTML produit par les scripts PHP et les feuilles de style CSS en générant par ci par là quelques balises supplémentaires.

Je vais conclure cette partie par un petit avant/après, juste pour vous montrer ce que l’on peut déjà faire avec quelques lignes de CSS.

php_step07_before_after
Comparaison avant/après de notre page Web


Frameworks

Plutôt que de refaire à chaque le design complet des sites Web en CSS, la tendance actuelle est à l’utilisation de frameworks, c’est-à-dire de boîtes à outils permettant la création du design de sites (graphisme, animation, interactions avec la page dans le navigateur Web, etc.) avec un minimum de codage pour le développeur. Un framework est un ensemble qui contient des codes HTML et CSS, des formulaires, des boutons, des outils de navigation et d’autres éléments interactifs, ainsi que généralement des extensions en JavaScript.

L’un des projets les plus populaires est le framework Bootstrap. Sa mise en œuvre est très simple (documentation ici): il suffit de le référencer par une balise <link> dans le header de votre document HTML, exactement de la même manière que pour une feuille de style CSS.

<html>

  <head>
    <meta charset="utf-8"/>
    <title>Gestion des emplois du temps</title>
    
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    ...
  </head>
  ...
</html>

php_step07_index13a
1ère utilisation de Bootstrap

L’utilisation d’un tel framework permet vraiment de faire des choses très sympathiques. Je vous renvoie à la documentation de Bootstrap pour démarrer et voir quelles sont les possibilités offertes. Après, c’est une question de temps, de tests et de patience ☺ Au final, on peut rapidement arriver au résultat ci-dessous (à tester ici) en ajoutant quelques class à notre code HTML.

php_step07_index13b
Un peu plus loin avec Bootstrap

Pour information, code source du formulaire HTML avec PHP, SQL, JavaScript et Bootstrap (fichier <code>index13b.php</code>)
<html>

  <head>
    <meta charset="utf-8"/>
    <title>Gestion des emplois du temps</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">

    <script language="javascript">
      function verifier() {
        var dmin = document.myform.datemin.value;
        var hmin = document.myform.heuremin.value;
        var dmax = document.myform.datemax.value;
        var hmax = document.myform.heuremax.value;

        if ( (dmin != '') && (tmin != '') && (dmax != '') && (tmax != '')) {
          var ddebut = new Date(dmin+'T'+hmin)
          var dfin   = new Date(dmax+'T'+hmax)

          if (ddebut<dfin) {
            document.myform.msgerreur.value = "";
            return true;
          } else {
            document.myform.msgerreur.value = "ERREUR";
            return false;
          }
        } else {
          document.myform.msgerreur.value = "";
          return true;
        }
      }
    </script>
  </head>

  <body>
    <?php
      // Ouverture du connecteur à la BdD une fois pour toute au début du script
      $dbh = new PDO('sqlite:planning.db') or die("impossible d'ouvrir la base sqlite");
      $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

      // Récupération des paramètres CGI éventuels
      // NB: si la valeur est 'none' alors le paramètre est ignoré
      if (array_key_exists('cours',$_GET)) {
        if ($_GET['cours'] != 'none') {
          $cours = $_GET['cours'];
        }
      }
      if (array_key_exists('salle',$_GET)) {
        if ($_GET['salle'] != 'none') {
          $salle = $_GET['salle'];
        }
      }
      if (array_key_exists('prof',$_GET)) {
        if ($_GET['prof'] != 'none') {
          $prof = $_GET['prof'];
        }
      }
      if (array_key_exists('datemin',$_GET)) {
        if ($_GET['datemin'] != '') {
          $datemin = $_GET['datemin'];
        }
      }
      if (array_key_exists('datemax',$_GET)) {
        if ($_GET['datemax'] != '') {
          $datemax = $_GET['datemax'];
        }
      }
      if (array_key_exists('heuremin',$_GET)) {
        if ($_GET['heuremin'] != '') {
          $heuremin = $_GET['heuremin'];
        }
      }
      if (array_key_exists('heuremax',$_GET)) {
        if ($_GET['heuremax'] != '') {
          $heuremax = $_GET['heuremax'];
        }
      }
    ?>

    <div class="container-fluid">
      <h1>Gestion des emplois du temps</h1>

      <div class="p-2">
        <form name="myform" action="index13b.php" method="GET" onsubmit="return verifier()">
          <div class="row g-3">
            <!-- Choix date et heure minimum -->
            <div class="col-sm-1">
              <label for="datemin" class="form-label">Date min</label>
              <input type="date" class="form-control" name="datemin" <?php if (isset($datemin)) { echo 'value="'.$datemin.'"'; }?> >
            </div>
            <div class="col-sm-1">
              <label for="heuremin" class="form-label">Heure min</label>
              <input type="time" class="form-control" name="heuremin" <?php if (isset($heuremin)) { echo 'value="'.$heuremin.'"'; }?> >
            </div>

            <!-- Choix date et heure maximum -->
            <div class="col-sm-1">
              <label for="datemax" class="form-label">Date max</label>
              <input type="date" class="form-control" name="datemax" <?php if (isset($datemax)) { echo 'value="'.$datemax.'"'; }?> >
            </div>
            <div class="col-sm-1">
              <label for="heuremax" class="form-label">Heure max</label>
              <input type="time" class="form-control" name="heuremax" <?php if (isset($heuremax)) { echo 'value="'.$heuremax.'"'; }?> >
            </div>

            <div class="col-sm-2">
              <label for="msgerreur" class="form-label">&nbsp;</label>
              <input type="text" class="form-control" name="msgerreur" value="" disabled>
            </div>
          </div>

          <br>

          <div class="row g-3">
            <!-- Choix du cours -->
            <div class="col-sm-2">
              <label for="cours" class="col-sm-5">Nom du cours</label>
              <select class="form-control" name="cours">
                <option value="none" selected>&#x3008;aucun&#x3009;</option>

                <?php
                  $sql = "select * from cours;";
                  foreach ($dbh->query($sql) as $row) {
                    echo '<option value="'.$row['numcours'].'"';

                    // S'il s'agit du cours dont l'id est dans le paramètre CGI cours, alors
                    // on ajoute l'option "selected" à cet élément de la liste
                    if (isset($cours)) {
                      if ($cours == $row['numcours']) {
                        echo ' selected';
                      }
                    }

                    echo '>'.$row['idcours'].' ('.$row['libcours'].')</option>';
                  }
                ?>
              </select>
            </div>

            <!-- Choix de la salle -->
            <div class="col-sm-2">
              <label for="salle" class="col-sm-5">Nom de la salle</label>
              <select class="form-control" name="salle">
                <option value="none" selected>&#x3008;aucun&#x3009;</option>

                <?php
                  $sql = "select * from salle;";
                  foreach ($dbh->query($sql) as $row) {
                    echo '<option value="'.$row['numsalle'].'"';

                    // S'il s'agit de la salle dont l'id est dans le paramètre CGI salle, alors
                    // on ajoute l'option "selected" à cet élément de la liste
                    if (isset($salle)) {
                      if ($salle == $row['numsalle']) {
                        echo ' selected';
                      }
                    }

                    echo '>'.$row['descsalle'].'</option>';
                  }
                ?>
              </select>
            </div>

            <!-- Choix du prof -->
            <div class="col-sm-2">
              <label for="prof" class="col-sm-5">Nom du prof</label>
              <select class="form-control" name="prof">
                <option value="none" selected>&#x3008;aucun&#x3009;</option>

                <?php
                  $sql = "select * from prof;";
                  foreach ($dbh->query($sql) as $row) {
                    echo '<option value="'.$row['numprof'].'"';

                    // S'il s'agit de l'enseignant dont l'id est dans le paramètre CGI prof, alors
                    // on ajoute l'option "selected" à cet élément de la liste
                    if (isset($prof)) {
                      if ($prof == $row['numprof']) {
                        echo ' selected';
                      }
                    }

                    echo '>'.$row['nomprof'].'</option>';
                  }
                ?>
              </select>
            </div>
          </div>

          <br>

          <!-- Bouton de soumission du formulaire -->
          <input type="submit" class="btn btn-primary" name="go" value="Rafraîchir">
        </form>
      </div>

      <div class="p-2">&#x263A;
        <?php
          // Dans la requête SQL, on mettra un '?' à chaque endroit où l'on voudra insérer un paramètre
          $sql = "select * from planning ".
                 "inner join cours on cours.numcours = planning.numcours ".
                 "inner join salle on salle.numsalle = planning.numsalle ".
                 "inner join prof on prof.numprof = planning.numprof ".
                 "where ( (1=1)";
          $params = array();

          // Si un critère de filtre (ex: variable $prof) existe, alors on ajoute une conjonction à la clause "where"
          // dans la requête SQL et on ajoute la valeur à la liste des paramètres pour l'exécution du statement
          if (isset($cours)) {
            $sql .= " and (planning.numcours=?)";
            array_push($params, $cours);
          }
          if (isset($salle)) {
            $sql .= " and (planning.numsalle=?)";
            array_push($params, $salle);
          }
          if (isset($prof)) {
            $sql .= " and (planning.numprof=?)";
            array_push($params, $prof);
          }

          if (isset($datemin) && isset($heuremin)) {
            $dhmin = $datemin.' '.$heuremin;
            $sql .= " and (?<=datetime(debut))";
            array_push($params, $dhmin);
          } else {
            if (isset($datemin)) {
              $sql .= " and (?<=date(debut))";
              array_push($params, $datemin);
            }
            if (isset($heuremin)) {
              $sql .= " and (?<=time(debut))";
              array_push($params, $heuremin);
            }
          }

          if (isset($datemax) && isset($heuremax)) {
            $dhmax = $datemax.' '.$heuremax;
            $sql .= " and (datetime(fin)<=?)";
            array_push($params, $dhmax);
          } else {
            if (isset($datemax)) {
              $sql .= " and (date(fin)<=?)";
              array_push($params, $datemax);
            }
            if (isset($heuremax)) {
              $sql .= " and (time(fin)<=?)";
              array_push($params, $heuremax);
            }
          }

          //echo '$sql = "'.$sql.'"<br>';

          // On termine proprement notre requête SQL
          $sql .= ") order by debut;";

          // Préparation du statement avec la requête SQL
          $stmt = $dbh->prepare($sql);

          // Exécution du statement avec les paramètres indiqués dans le tableau
          $stmt->execute($params);

          // Récupération du résultat de la requête
          $res  = $stmt->fetchAll();

          echo '<table class="table table-sm table-striped">';
          echo '<thead><tr><th>num</th><th>début</th><th>fin</th><th>cours</th><th>salle</th><th>prof</th></tr></thead>';
          echo '<tbody>';
          // Parcours du résultat
          foreach ($res as $row) {
            echo '<tr>';
            echo '<td>'.$row['numcreneau'].'</td>';
            echo '<td>'.$row['debut'].'</td>';
            echo '<td>'.$row['fin'].'</td>';
            echo '<td>'.'<a href="" title="'.$row['libcours'].'">'.$row['idcours'].'</a>'.'</td>';
            echo '<td>'.$row['descsalle'].'</td>';
            echo '<td>'.'<a href="infos_prof01.php?prof='.urlencode($row['numprof']).'" title="infos prof #'.$row['numprof'].'">'.$row['nomprof'].'</a>'.'</td>';
            echo '</tr>';
          }
          echo '</tbody>';
          echo '</table>';
        ?>
      </div>

      <hr>
      Copyright © 2022 Manuel Munier
      <br>
      <a href="https://munier.perso.univ-pau.fr/">https://munier.perso.univ-pau.fr/</a>

    </div>
  </body>

</html>

Conclusion

J’espère vous avoir convaincu que pour concevoir votre site Web (dynamique), le point de départ ce sont les scripts PHP (avec SQL) et le code HTML. La mise en page, que ce soit avec des styles CSS écrits à la main ou bien à l’aide d’un framework tel que Bootstrap, ne se fait qu’à la fin. En tout cas, pas avant que la “mécanique” de votre site soit opérationnelle !

Quand on construit une maison, on commence bien par monter les murs avant de coller la tapisserie !

Dans le jargon informatique c’est ce que l’on appelle le frontend et le backend :

  • frontend → partie visible pour l’utilisateur: interface graphique, etc.
  • backend → la mécanique qui fait tourner votre site, invisible pour l’utilisateur: scripts PHP, requêtes SQL, etc.