Mini-cours de PHP - MySQL

Partie VII

Ce chapitre est consacré aux fichiers : créés, lus, analysés.

Gestion des fichiers

Suivez bien ce chapitre, car c'est (presque) le même en C, C++, Java.
Pour des raisons de sécurité, l'écriture et la lecture de fichiers ne sont pas autorisées pour les langages qui s'exécutent coté-client, tel que JavaScript.

Écriture

Pour écrire ou ajouter du contenu dans un fichier, cliquez ici.

txtWrite (code complet) :

<?php
  $texte=htmlspecialchars($_POST['texte']);
  $mode="w"; if (isset($_POST['ajouter'])) $mode="a";
  $f=fopen("texte.txt",$mode);
  fwrite($f,$texte);
  fclose($f); // fermeture de la connexion au fichier
  header("Location:txtRead.php");
?>

Info sur les fonctions PHP : fopen(), fwrite(), fclose()

Lecture

txtRead (extrait) :

<?php
  $fichier="texte.txt";
  $texte="";
  if(!file_exists($fichier)) {
    $f=fopen($fichier,"w");
  }else{
    $f=fopen($fichier,"r");
    $texte=fread($f,filesize($fichier));
  }
  fclose($f); // fermeture de la connexion au fichier
?>
<<!DOCTYPE html>
...
        <form name="ajouter" id="ajouter" method="post" action="txtWrite.php">
          <p>
            Texte :
            <textarea name="texte" required="required" rows="10" cols="70">
<?php echo $texte; ?>
</textarea>
          </p>
          <p>
            <input type="checkbox" name="ajouter" /> Ajouter du contenu à la fin
          </p>
          <p>
            <input value="Écrire/Ajouter" type="submit" />
          </p>
        </form>

Info sur les fonctions PHP : file_exists(), fread(), filesize()

Ici, tout le fichier est lu. Cependant, il est possible de fixer le nombre d'octets qui doivent être lus.

Pour lire le contenu dans un fichier, cliquez ici.

Pour lire le code-source d'une page web, cliquez ici

Compteurs

Il est facile de créer un compteur en PHP. Il suffit d'enregistrer un caractère (ASCII étendu imprimable) dans un fichier à chaque action (telle que visite d'une page web, clic sur un bouton, ...). Le code peut être écrit en une seule ligne.

accueil.php :

...
$f=fopen("compteur.txt","a"); fwrite($f,"x"); fclose($f);
...

Pour connaître le nombre d'actions, il suffit de lire la taille du fichier.

mesVisites_ajjke.php :

echo filesize("compteur.txt");

Le suffixe _ajjke garantit la confidentialité.

Enregistrer le moment de l'action

Il est aussi possible d'enregistrer le moment de l'action puis de connaître leur nombre par jour, par mois, ...

$f=fopen("compteur2.txt","a"); fwrite($f,date("Y-m-d H:i:s;")); fclose($f);

Choisir un bon format d'enregistrement de la date permet de gagner en facilité de codage et en rapidité d'exécution. Pour permettre un tri rapide, le format présentera les parties les plus importantes au début (à gauche de l'expression), comme pour un nombre. Pour rappel, dans le nombre entier, 123, le caractère le plus significatif est 1 car il représente les centaines. Il en ira de même pour les dates. Le format est donc du type AAAA-MM-JJ. Les séparateurs, ici (-), ne font que faciliter la lecture (des humains). Ce type de format, très utilisé en informatique (car logique). Il correspond à la norme ISO 8601.

Conseil : Si vous indiquez une date dans le nom d'un fichier, il est également préférable d'utiliser ce format pour repérer plus facilement ce fichier dans un listing de noms de fichiers. Au lieu de nommer un fichier :
rapport du 31 décembre 2020.txt, il vaut mieux le nommer :
rapport_2002-12-31.txt, ou mieux encore : rapports/2000-12-31.txt

La fonction date("Y-m-d H:i:s") retourne une string au format AAAA-MM-JJ hh:mm:ss (représentant le moment actuel). Les séparateurs sont conventionnels. À noter que le code utilisé ajoute un (;) final. Ce séparateur additionnel permet de séparer les dates dans le fichier. Au final, le contenu du fichier se présentera comme ceci :

2021-03-01 17:19:31;2021-03-02 17:20:25;2021-04-01 17:20:25;2021-06-01 17:20:25;2021-06-02 17:20:25;

Réduire la taille du fichier

Pour réduire la taille du fichier, il est possible de supprimer les séparateurs (car facultatifs). Ainsi, le fichier suivant est plus petit mais offre la même information :

20210301171931;20210302172025;20210401172025;20210601172025;20210602172025;

Il est également possible de ne pas prendre en compte les secondes, ni les minutes, ni ... La taille du fichier peut alors être encore réduite.

20210301;20210302;20210401;20210601;20210602;

accueil.php :

Exemple de code pour des statistiques journalières :

...
$f=fopen("compteur2.txt","a"); fwrite($f,date("Y-m-d;")); fclose($f);
...

Bien que le jour de l'action soit enregistré, on peut ne pas en tenir compte dans l'immédiat (et en tenir compte ultérieurement). Qui peut le plus, peut le moins.

Présentation choisie : (statistiques mensuelles) :

2021-01 : 145
2021-02 : 612
2021-03 : 3
2021-04 : 1024
2021-05 : 0
2021-06 : 42
...

mesVisites_ajjke.php :

Code pour obtenir une telle présentation :

$fichier = "compteur2.txt";
$f = fopen($fichier, "r"); $contenu = fread($f, filesize($fichier)); fclose($f);
$tab = explode(";", $contenu); $nb_dates = count($tab) - 1; /* -1 à cause du dernier ";" */

$p = 0; /* pointeur = index de la dernière date traitée */
$fin = false; /* indique si toutes les dates ont été traitées */
for ($aaaa = 2021; $aaaa < 2022; $aaaa++) { /* boucle des années */
  for ($j = 1; $j < 13; $j++) { /* boucle des mois */
    $cpt_mois = 0;
    $mm = sprintf("%02d", $j); $m2 = sprintf("%02d", $j + 1);
    $mois_print = $aaaa . "-" . $mm . " : "; /* pour plus de lisibilité */
    $mois_suivant = $aaaa . "-" . $m2;

    if (!$fin) {

      for ($i = $p; $i < $nb_dates; $i++) { /* boucle des dates */
        if ($tab[$i] < $mois_suivant) {
          $p = $i + 1; $cpt_mois++;
          if ($p == $nb_dates) {
            echo $mois_print . $cpt_mois . "<br>"; $fin = true;
          }
        }
        else {
          echo $mois_print . $cpt_mois . "<br>"; break;
        }
      } /* fin de la boucle des dates */

    }
    else {
      echo $mois_print . $cpt_mois . "<br>";
    } /* fin du if */

  } /* fin de la boucle des mois */

} /* boucle des années */

Dans la boucle for ($aaaa = 2021; $aaaa < 2022; $aaaa++) il suffit de modifier les bornes : 2021 et 2022.


Et, tout en affichant les mêmes statistiques mensuelles, la taille du fichier peut encore être réduite.

03;03;04;06;06;

Le code du fichier accueil.php doit alors être légèrement modifié :

...
$f=fopen("compteur3.txt","a"); fwrite($f,date("m;")); fclose($f);
...

Et le fichier, traitant le fichier TXT, contiendra un code très semblable au code vu précédemment.

simple_html_dom.php

Le fichier simple_html_dom.php est une librairie qui permet d'analyser des fichiers écrits en HTML.

Via quelques lignes de code, il est alors possible de récupérer les parties d'un site web qui vous intéressent.

La réciproque est vraie. Un autre programmeur PHP peut récupérer ce qui l'intéresse de VOTRE site web. Tout ce que vous pouvez lire peut être récupéré et stocké dans un fichier.

dico8.php  (Exemple de code)

<?php
  $debut="";
  $borne1a="";
  $borne1b="";
  $borne2="";

  $contenu=""; $tpsDebut = microtime(true);$i=0;
  for ($i=0;$i<26;$i++) {
    $texte=file_get_contents($debut.chr(65+$i).".php");
    $borne1=$borne1a.chr(65+$i).$borne1b;
    $pos1=strpos($texte,$borne1)+strlen($borne1);
    $pos2=strpos($texte,$borne2);
    $contenu.=substr($texte,$pos1,$pos2-$pos1);
  } // $contenu = une suite de <li> contenant tous les liens (un lien par mot)

  $nomFichier="dico".chr(64+$i).".htm";
  $fdico=fopen($nomFichier,"w"); // crée le fichier HTML
  // Les fichiers CSS peuvent ne pas exister
  fwrite($fdico,'<!DOCTYPE html><html lang="fr" xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
  <head><meta charset="UTF-8" /><link rel="stylesheet" href="../../../cours4.css" />
    <link rel="stylesheet" type="text/css" href="dico.css" /><title>Dico</title></head>
    <body><div id="container"><article>');
  $prefix="";

  require("simple_html_dom.php");

  $html = str_get_html($contenu);
  $liens = $html->find('a');// $liens = tableau de tous les <a> (un lien par mot)

  $cpt=0; // pour compter le nombre de mots
  foreach($liens as $e) {
    $a=$e->innertext; // $a = le contenu de la balise <a>
    $a=substr($a,0,strpos($a," <i>"));
    $a=mb_strtolower(trim($a)); // $a = le mot formaté

    $link=$e->href; // $link = valeur de l'attribut href du lien

    $html = file_get_html($prefix.$link); // $html = arbre du fichier définissant le mot
    $art=$html->find('.dico',0);  // $art = la zone contenant les data

    $article=str_get_html($art); // $article= arbre de la zone des data
    $y=$article->find('p'); // $y = tableau des paragraphes
    $n=count($y); // $n = nombre de paragraphes

    $h1='<h1>'.$a.'</h1><div>';
    $y[0]=strip_tags($y[0]);$z=strlen($y[0]);$h1.='<p>'.substr($y[0],2,$z-4).'</p>';
    $y[1]=strip_tags($y[1]);$h1.='<p>'.substr($y[1],13).'</p>';
    $y[2]=strip_tags($y[2]);$h1.='<p>'.substr($y[2],9).'</p>';
    if($n>3) {$y[3]=strip_tags($y[3]);$h1.='<p>'.substr($y[3],12).'</p>';}
    if($n>4) {$y[4]=strip_tags($y[4]);$h1.='<p>'.substr($y[4],13).'</p>';}

    fwrite($fdico,$h1.'</div>'); // $h1 = code HTML reformaté contenant les data
    $article->clear(); $html->clear();
    $cpt++;
  }

  unset($article);unset($html);

  // les fichiers JavaScripts peuvent ne pas exister
  fwrite($fdico,'</article></div><script src="../../../adapter.js"></script>
  <script src="dico.js"></script></body></html>'); fclose($fdico);

  $s=(microtime(true)-$tpsDebut)/1000;
  echo "Fichier '$nomFichier' créé en $s seconde(s); $cpt définitions récupérées.";

dico.js (code complet) :

completer();

function completer(){

/* code CSS (valide mais non-exécuté par le navigateur en "mode lecture")
div+p+p:before {content:"Définition(s) : ";}
div+p+p+p:before {content:"Exemple(s) : ";}
div+p+p+p+p:before {content:"Synonyme(s) : ";}
div+p+p+p+p+p:before {content:"Contraire(s) : ";}
d'où le présent code JavaScript */

   tableau=document.querySelectorAll("article div p:nth-child(2)");
   for(i=0,taille=tableau.length;i<taille; i++) {
     tableau[i].firstChild.nodeValue = "Définition(s) : "+tableau[i].firstChild.nodeValue;
   }
   tableau=document.querySelectorAll("article div p:nth-child(3)");
   for(i=0,taille=tableau.length;i<taille; i++) {
     tableau[i].firstChild.nodeValue = "Exemple(s) : "+tableau[i].firstChild.nodeValue;
   }
   tableau=document.querySelectorAll("article div p:nth-child(4)");
   for(i=0,taille=tableau.length;i<taille; i++) {
     tableau[i].firstChild.nodeValue = "Synonyme(s) : "+tableau[i].firstChild.nodeValue;
   }
     tableau=document.querySelectorAll("article div p:nth-child(5)");
   for(i=0,taille=tableau.length;i<taille; i++) {
     tableau[i].firstChild.nodeValue = "Contraire(s) : "+tableau[i].firstChild.nodeValue;
   }
   h1=document.querySelectorAll("h1");
   for(i=0,taille=h1.length;i<taille; i++) {
     h1[i].setAttribute("onclick","aff(this)");
     h1[i].nextElementSibling.style.display = "none";
   }
}

function aff(h1){
  div=h1.nextElementSibling;
  if (div.style.display == "none") {
    div.style.display = "block";
  } else {
    div.style.display = "none";
  }
}

Rappel : Une méthode ou une propriété ne s'applique qu'à un objet. Le nom qui précède le nom de la méthode ou de la propriété est le nom de l'objet. Le nom d'une méthode ou d'une propriété est précédé d'un point. La méthode se distingue d'une propriété par le fait que son nom est suivi d'une parenthèse ouvrante "(". La fonction se distingue de la méthode par le fait que son nom n'est pas précédé d'un point.

dico.css (code complet) :

h1{text-align:left;
  margin-top:0px;
  background-color:#B9D100  /* couleur de fond = article*/
}
.no{display:none}

L'utilisation de la librairie est expliqué sur simplehtmldom.sourceforge.net. Manuel.

Création de PDF

Tout est expliqué sur ce site : fpdf.org

Fin de ce mini-cours.