Petits codes PHP

Voici quelques bouts de codes PHP tout faits. Vous pouvez tout reprendre comme bon vous semble !

  1. Mesurer le temps de génération d'une page
  2. Convertir une image en base64
  3. Un calendrier HTML en PHP
  4. Supprimer un fichier en PHP
  5. Supprimer le canal alpha d’une image en PHP avec GD
  6. Faire une archive ZIP d’un dossier et sous dossiers en PHP
  7. Créer une liste des fuseaux horaires en PHP
  8. Parser des entêtes HTTP (headers)

Mesurer le temps de génération d'une page

Le code suivant permet de chronométrer le temps de génération des pages par PHP.

Attention : seul le temps de génération de la page est mesuré. Ni le temps de la requête DNS, ni le temps de téléchargement de la page ne sont pris en compte (pour cela il faut coupler PHP et JavaScript).

<?php
    $time = microtime();          // Actual timestamp
    $time = explode(' ', $time);  // separate integer and fractional part of time
    $begin = $time[0]+$time[1];   // Needed to get "0.000025 sec" instead of "2.5E-5 sec" format

// YOUR CODE HERE

    $time = microtime();
    $time = explode(' ', $time);
    $end = $time[0]+$time[1];

    echo round(($end - $begin),6).' seconds';
?>

Sous PHP 5, c'est même encore plus simple :

<?php
    $begin = microtime(TRUE);

// YOUR CODE HERE

    $end = microtime(TRUE);
    echo round(($end - $begin),6).' seconds';
?>

Sommaire

Convertir une image en base64

Base64 est la représentation en texte (chaine de caractères) d'un fichier binaire comme une image. Quand on veut transférer une image sur un système ne pouvant traiter que du texte, on peut transformer les fichiers en BASE64 pour les mettre en texte.

Les fonctions suivantes peuvent alors être utiles : la première lit une image, la transforme en texte au format BASE64. La seconde fait l'inverse : elle écrit une image à partir d'un code en BASE64.

<?php

// conversion d'une image en BASE64

function file2base64($source) {
    $bin_data_source = fread(fopen($source, "r"), filesize($source)); // reading as binary string
    $b64_data_source = base64_encode($bin_data_source);               // BASE64 encodage
    return $b64_data_source;
}	


// création d'une image à partir d'un code en BASE64

function base642file($b64_data_target, $image_target_name) {
    $bin_data_target = base64_decode($b64_data_target);        // base64 decodage
    $image_target = fopen($image_target_name, 'wb');           // Create a file
    if (fwrite($image_target, $bin_data_target))               // Write the file
        return TRUE;
    else
        return FALSE;
}

$source = 'image.png';
$base64_data = file2base64($source);

//

$data64 = 'iVBORw0KGgoAAAANSU [ … / … ] FTkSuQmCC';
base642file($data64, 'destination.png');

?>

Cette méthode :

Sommaire

Un calendrier HTML en PHP

Voici une fonction qui génère la page du mois actuel d'un calendrier :

<?php

function afficher_calendrier() {
    $ce_mois_lettres = date('F');
    $jours_semaine = array('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su');

    $premier_jour = mktime('0', '0', '0', date('m'), '1', date('Y'));

    // haut du tableau
    $calendar = '<table id="calendrier">'."\n";
    $calendar.= '<caption>'.$ce_mois_lettres.'</caption>'."\n";
    $calendar.= '<tr><th>'.implode('</th><th>', $jours_semaine).'</th></tr><tr>';

    // un nouveau mois ne commence pas forcément le premier jour de la semaine (lundi)
    $decalage_jour = date('w', $premier_jour-'1');
    if ($decalage_jour > 0) {
        for ($i = 0; $i < $decalage_jour; $i++) {
            $calendar.=  '<td></td>';
        }
    }

    // création du tableau
    $date_t = date('t');
    $date_d = date('d');

    for ($jour = 1; $jour <= $date_t; $jour++) {
        $calendar.= '<td';

        // ajoute une classe CSS sur aujourd'hui
        $calendar .= ($jour == $date_d) ? ' class="active"' : '';

        $calendar.= '>';
        $calendar.= $jour;
        $calendar.= '</td>';
        $decalage_jour++;
        if ($decalage_jour == '7') {
            $decalage_jour = '0';
            $calendar.=  '</tr>'."\n";
            $calendar.= ($jour < $date_d) ? '<tr>' : '';
        }
    }

    // complète le tableau HTML avec des cases vides à la fin
    if ($decalage_jour > '0') {
        for ($i = $decalage_jour; $i < '7'; $i++) {
            $calendar.= '<td></td>';
        }
        $calendar.= '</tr>'."\n";
    }
    $calendar.= '</table>'."\n";

    return $calendar;
}

?>

Le calendrier généré possède l'ID CSS "calendrier" ; la date actuelle possède la classe CSS "active".

Les abréviations des jours sont définissables au début de la fonction, et le le nom du mois est affiché en Anglais. Pour l'avoir en Français ou dans une autre langue, on peut par exemple utiliser un switch sur $ce_mois_lettres.

Sommaire

Supprimer un fichier en PHP

Si vous devez supprimer un fichier (image, ou autre) en PHP à partir d'une requête d'un utilisateur, il convient de faire gaffe : never trust user input.

Le problème

Considérons ce code :

$dossier = 'sous_dossier/';
$fichier = $_GET['nom_du_fichier'];

if (TRUE === unlink($dossier.$fichier)) echo 'fichier supprimé';

Il marche très bien : ce code supprime un fichier dont le nom est contenu dans l'URL.
Si je vais sur cette URL : http://monsite/page.php?nom_du_fichier=image.jpg, alors le fichier /sous_dossier/image.jpg sera supprimé. Bien.

Maintenant, imaginons qu'un utilisateur utilise cette URL : http://monsite/page.php?nom_du_fichier=../page.php. Vous voyez ? Le fichier supprimé sera donc /sous_dossier/../page.php, autrement dit /page.php !

Ceci n'est pas acceptable : n'importe quel fichier peut-ainsi être supprimé, y compris des fichiers importants !

Une solution

La solution que j'ai retenue, c'est de partir du principe que les fichiers que l'utilisateur gère se trouvent dans un dossier à part des fichiers PHP. Par exemple, si ce sont des fichiers images, ils sont dans un dossier /image. Nous allons donc lister tous les fichiers dans ce dossier, et comparrer au fichier dans le $_GET. S'il y a correpondance, alors c'est bon, sinon on ne fait rien :

    $dossier = 'sous_dossier';
    $liste = scandir($dossier); // listage des fichiers
    $fichier = $_GET['nom_du_fichier'];

    $nb_fichier = count($liste);
    for ($i = 0 ; $i < $nb_fichiers ; $i++) {
        if ($liste[$i] == $fichier and !($liste[$i] == '..' or $liste[$i] == '.')) {
            if (TRUE === unlink($dossier.$liste[$i])) echo 'fichier supprimé';
        }
    }

Ici, j'ai même rajouté un test : le fichier ne dois pas être '.' ni '..' (qui sont tout le dossier et le dossier parent).

Évidement, il convient d'ajouter les traditinnels « htmlspecialchars() »

Sommaire

Supprimer le canal alpha d’une image en PHP avec GD

J’ai passé quelques heures sur ce problème : j’ai une image PNG avec une région transparente, et je veux la transformer en JPG avec la transparence mise en blanc. Le soucis, c’est qu’à l’arrivé je me retrouve avec une image où transparence est remplacée par du noir !

Le code suivant fonctionne à merveille (vous pouvez remplacer la fonction « imagejpeg » par « imagepng », ça marche aussi). Ce qui compte ce sont les autres fonctions de manipulation d’image avec GD.

$image = 'troll-troll-dad-dance-jump-l.png';

function remove_alpha($FichierSource) {

    $FichierDest = 'destination.jpg';
    // largeur et hauteur
    list($width, $height) = getimagesize($FichierSource);

    // Crée une ressource image de destination
    $IMG_dest = imagecreatetruecolor($width, $height);
    // Remplie cette image de blanc
    imagefill($IMG_dest, 0, 0, imagecolorallocate($IMG_dest, 255, 255, 255));

    // Ouvre le fichier source en PNG.
    $IMG_source = imagecreatefrompng($FichierSource);

    // Place le fichier PNG sur le fond blanc
    imagecopy($IMG_dest, $IMG_source, 0, 0, 0, 0, $width, $height);
    imagedestroy($IMG_source);

    // enregistrement en JPG, qualité 90%
    imagejpeg($IMG_dest, $FichierDest, 90);
    imagedestroy($IMG_dest);

return $FichierDest;	
}

echo '<img src="'.remove_alpha($image).'"/>';

Sommaire

Faire une archive ZIP d’un dossier et sous-dossiers en PHP

En PHP on peut ajouter un fichier dans uen archive ZIP. Pour ajouter un dossier, il faut ajouter les fichiers un par un.

L’idée est simple : on fait une fonction récursive à l’aide de GOTO. Listant les entrées d’un dossier, si l’entrée est un fichier, on l’ajoute, si c’est un dossier on reboucle sur la fonction elle même avec le fichier en question.

Le code qui suit utilise la POO ainsi que l’instruction goto apparue en PHP 5.3. Notez qu’il est sûrement possible de faire beaucoup plus simple avec les bibliothèques Gzip ou autres.

// nouvelle archive
$zip = new ZipArchive;

// ouverture
if ($zip->open('test.zip', ZipArchive::CREATE) === TRUE) {
   $folder = 'mon_dossier';
   inputfolder: // "goto" apparu en php >= 5.3.0

   // ouvre le dossier
   if ($handle = opendir($folder)) {

      // parcourt les entrées une par unes.
      while (FALSE !== ($entry = readdir($handle))) {

         // on exclu les dossiers parents (..) et courant (.),
         // ainsi que les fichiers dont on n’a pas les droits en lecture
         if ($entry != "." AND $entry != ".." AND is_readable($folder.'/'.$entry)) {

            // si c’est un dossier, on reboucle avec le GOTO
            if (is_dir($folder.'/'.$entry)) {
               // ne surtout pas oublier ceci :)
               $folder =  $folder.'/'.$entry;
               goto inputfolder;
            }

            // on ajoute le fichier (l’arborescence d’origine est conservée)
            $zip->addFile($folder.'/'.$entry, $folder.'/'.$entry);
         }
      }

      // ferme le dossier
      closedir($handle);
   }

   // ferme l’archive ZIP
   $zip->close();

   echo '<p>ok : <a href="test.zip">test.zip</a></p>';
} else {
   echo '<p>échec lors du open()</p>';
}

Sommaire

Créer une liste des fuseaux horaires

Ce code génère une liste déroulante (de type optgroup/option) des fuseaux horaires, regroupés par continent et affichant les décallages (+2h, +3h…). Il fonctionne pour PHP 5.2 et supérieur. capture du résultat du code

Retourne le formulaire html, dans une liste d’options.
function form_fuseau_horaire() {
   Liste tous les fuseaux, sous la forme "Europe/Paris"
   $all_timezones = timezone_identifiers_list();
   $liste_fuseau = array();
   $cities = array();
   Les séparre par continent, en sous-tableaux
   foreach($all_timezones as $tz) {
      $spos = strpos($tz, '/');
      if ($spos !== FALSE) {
         $continent = substr($tz, 0, $spos);
         $city = substr($tz, $spos+1);
         $liste_fuseau[$continent][] = array('tz_name' => $tz, 'city' => $city);
      }
      Même chose pour UTC, sauf que lui n’a pas de continent…
      if ($tz == 'UTC') {
         $liste_fuseau['UTC'][] = array('tz_name' => 'UTC', 'city' => 'UTC');
      }
   }
   $form = '<p>';
   $form .= '<label for="fuseau_horaire">Fuseau Horaire :</label>';
   $form .= '<select id="fuseau_horaire" name="fuseau_horaire">' ;
   foreach ($liste_fuseau as $continent => $zone) {
      $form .= '<optgroup label="'.ucfirst(strtolower($continent)).'">'."\n";
      foreach ($zone as $fuseau) {
         $form .= '<option value="'.htmlentities($fuseau['tz_name']).'"';
         Affiche les informations sur le décallage : (UTC+02:30)
         $timeoffset = date_offset_get(date_create('now', timezone_open($fuseau['tz_name'])) );
         $formated_toffset = '(UTC'.(($timeoffset < 0) ? '–' : '+').str_pad(floor((abs($timeoffset) / 3600)), 2, '0', STR_PAD_LEFT).':'.str_pad( floor((abs($timeoffset) % 3600) / 60), 2, '0', STR_PAD_LEFT).') ';
         $form .= '>'.$formated_toffset.' '.htmlentities($fuseau['city']).'</option>'."\n";
      }
      $form .= '</optgroup>'."\n";
   }
   $form .= '</select> '."\n";
   $form .= '</p>'."\n";
   return $form;
}

Sommaire

Parser des entêtes HTTP (headers)

Ce code retourne un tableau des entêtes d’une requête PHP. Il prend en entrée soit une chaine des entêtes brutes (retournées par exemple par CURL), soit un tableau à une dimension (par exemple celui de $http_response_header créée par la fonction file_get_contents).

Il retourne un tableau associatif des entêtes HTTP :

if (!function_exists('http_parse_headers')) {
   function http_parse_headers($raw_headers) {
      $headers = array();
      $array_headers = (is_array($raw_headers) ? $raw_headers : explode("\n", $raw_headers));
      foreach ($array_headers as $i => $h) {
         $h = explode(':', $h, 2);
         if (isset($h[1])) {
            $headers[$h[0]] = trim($h[1]);
         }
      }
      return $headers;
   }
}

Il retourne un tableau associatif des entêtes HTTP (dont le contenu peut varier, toutes les entêtes n’étant pas pareil sur tous les serveurs) :

Array
(
    [0] => HTTP/1.1 200 OK
    [Date] => Sat, 29 May 2004 12:28:14 GMT
    [Server] => Apache/1.3.27 (Unix)  (Red-Hat/Linux)
    [Last-Modified] => Wed, 08 Jan 2003 23:11:55 GMT
    [Accept-Ranges] => bytes
    [Content-Length] => 438
    [Connection] => close
    [Content-Type] => text/html
    …
    …
)

Sommaire

Ressources

Sommaire

Page créée en janvier 2011. Dernière mise à jour le dimanche 31 janvier 2016.
Adresse de la page : http://lehollandaisvolant.net/tuto/php/