Utilisation Avancée de PHP§

Fonctionnalités§

Afficher les erreurs§

Il est possible d’utiliser PHP en mode débogage lors de la phase de conception de vos scripts.

Pour cela, deux fonctions doivent être appelées dans le script :

<?php
 ini_set('display_errors', '1') ;
 error_reporting(E_ALL) ;
 ... // instructions du script
?>

Note

Il est aussi possible de configurer l’affichage des erreurs dans le fichier de configuration php.ini (nécessite d’être root)

Redirection§

Les codes de statut HTTP 301 et 302 permettent de faire une redirection, respectivement permanente ou temporaire. L’URL vers laquelle rediriger se trouve dans l’en-tête HTTP Location.

Astuce

Essayez : curl -v http://www.google.com

Nous avons vu que PHP permettait de redéfinir ou d’ajouter des en-têtes à la réponse HTTP.

<?php
 // Il ne doit y avoir aucune sortie avant ces lignes
 http_response_code(302); // temporaire ; ou 301 = permanente
 header('Location: urlDeRedirection.php?parametres');
 exit();
?>

Note

Il est possible de rediriger vers une page via une URL relative ou une URL externe. On peut même faire une redirection vers la même page mais avec des paramètres différents !

Sécuriser des pages PHP§

Contrôle d’accès sur serveur Apache§

Nécessité de séparer public/privé (admin, ...), plusieurs possibilités:

  • Sessions PHP (vu plus tard dans le cours)
  • Contrôle d’accès côté serveur
    • limiter l’accès à certains fichiers aux seuls utilisateurs autorisés

Pour mettre en place un contrôle d’accès, il faut créer deux fichiers :

  1. Un fichier .htaccess qui contient l’adresse du .htpasswd et définit les options du contrôle d’accès.
  2. Un fichier .htpasswd qui contient une liste de logins/mots de passe des utilisateurs autorisés à accèder aux pages contenues dans le dossier du fichier .htaccess.

Note

Chaque fichier .htaccess protège les pages du répertoire dans lequel il se trouve. Pour protéger plusieurs pages, il est donc nécessaire de dupliquer ce fichier, mais il est préférable de le faire pointer sur un fichier .htpasswd unique.

Le fichier .htaccess§

Exemple :

AuthName "Message de l'invité"
AuthType Basic
AuthUserFile "/home/univ-lyon1/pxxxxxxx/
              public_html/admin/.htpasswd"
Require valid-user

Le champ AuthName correspond au message affiché lors de la tentative d’accès à une ressource sous contrôle d’accès.

Le champ AuthUserFile est le chemin absolu vers le fichier .htpasswd.

Note

La fonction PHP realpath() permet de récupérer le chemin absolu du fichier .htpasswd.

Le fichier .htpasswd§

Le fichier .htpasswd se compose de lignes suivant le format : login:mot_de_passe_crypté.

Il est possible d’afficher les mots de passe en clair. Mais ils sont alors visibles pour qui à les droits de lecture sur le serveur.

Pour crypter les mots de passe du fichier .htpasswd, PHP propose la fonction crypt().

Exemple sans cryptage :

autralian32:kangourou
kikoo69:totolitoto
monuser:monpass

Exemple avec cryptage :

autralian32:$1$nRSP5U.A$e8FqI6QTq/Bp6lNMjBUMO1
kikoo69:$1$riMIdCaV$6GO24RT5v4iwrSzChZq720
monuser:$apr1$MWZtd0xs$mRBeIn.alFLzJZe4.r07U1

Astuce

Comme il est possible de manipuler des fichiers en PHP, il est aussi possible d’écrire les fichiers de contrôle d’accès directement depuis PHP.

Par exemple, un formulaire accessible seulement par l’administrateur pourrait permettre d’ajouter de nouveaux utilisateurs.

Envoyer des fichiers§

Grâce à PHP, il est possible pour l’utilisateur de transmettre un fichier au serveur par l’intermédiaire des formulaires.

Au moment de l’envoi du formulaire (soumission via submit), le fichier est téléchargé par le serveur (on parle d’un “upload” côté client).

Le serveur peut ensuite manipuler le fichier puis l’enregistrer.

Formulaire d’envoi de fichier§

Il est possible, dans les formulaires HTML, de définir un champ de type fichier (<input type="file" />) permettant de transmettre des fichiers au serveur.

Le formulaire devra simplement comporter l’attribut d’encodage indiquant l’envoi de fichier(s).

<form action="traitement.php" method="post"
      enctype="multipart/form-data">
      ...
<input type="hidden"
  name="MAX_FILE_SIZE" value="1048576" />
<input type="file" name="fichier" />
...
</form>

Note

Du fait du format et du volume des données, l’envoi de fichiers n’est possible qu’en Post.

Le champ <input type="hidden" /> permet de spécifier une taille maximale de fichier.

Sauvegarder un fichier sur le serveur§

Les fichiers envoyés depuis un formulaires sont stockées dans une variable différente de $_GET ou $_POST: il s’agit de la variable $_FILES

Les fichiers sont stockés sous la forme d’un tableau à deux dimensions. L’accès fichier par fichier se fait en utilisant la valeur de l’attribut name définit dans le formulaire.

Variable Signification
$_FILES[‘fichier’][‘name’] Nom du fichier envoyé
$_FILES[‘fichier’][‘type’] Type du fichier (ex: image/png)
$_FILES[‘fichier’][‘size’] Taille du fichier en octets
$_FILES[‘fichier’][‘tmp_name’] Emplacement temporaire du fichier sur le serveur
$_FILES[‘fichier’][‘error’] Code d’erreur (0 si pas d’erreur)

Vérifier le fichier reçu§

Généralement, côté serveur, le type de fichier attendu ainsi que sa taille limite sont connus à priori. Exemple de script PHP permettant d’effectuer toutes ces vérifications :

<?php
 if (isset($_FILES['fichier']) &&
     $_FILES['fichier']['error'] == 0 &&
     $_FILES['fichier']['size'] <= 1 * 1024 * 1024)
 {
   $infosfichier = pathinfo($_FILES['fichier']['name']);
   $ext_upload = $infosfichier['extension'];
   if (in_array($ext_upload, array('jpg', 'gif', 'png')))
   {
     move_uploaded_file(
       $_FILES['fichier']['tmp_name'],
       'uploads/'.basename($_FILES['fichier']['name'])
     );
   }
 }
?>

Avertissement

La taille du fichier est à vérifier côté serveur, puisque le <input type="hidden" /> est modifiable par le client (il ne sert qu’à la pré-validation par le navigateur)

Note

N’hésitez pas à consulter la documentation PHP pour les fonctions pathinfo() et move_uploaded_file().

Les cookies§

Les cookies sont des données enregistrées côté client.

L’utilité des cookies est de sauvegarder des données relatives au client, comme la langue qu’il a choisi.

L’utilisation des cookies se fait en deux temps :

  1. Création et enregistrement du cookie
  2. Consultation des données contenues dans le cookie

Les sessions§

L’intérêt des sessions est de pouvoir manipuler dans une variable de page en page. Les variables de type session sont conçues pour garder en mémoire des informations relatives au client.

Une session est une sorte de “boite” spécifique à un visiteur donné et contenant des variables.

Contrairement aux cookies, les variables de session sont stockées côté serveur et ne sont donc pas directement accessibles au client. HTTP étant un protocole state-less, un unique cookie contient l’identifiant de l’utilisateur, et permet à PHP de retrouver sa “boite” de page en page.

Note

L’identifiant est stocké en cookie, il est donc accessible à l’utilisateur. Cependant, il est aléatoire et suffisemment grand pour être considéré indevinable par un éventuel imposteur. Attention cependant à ne pas se le faire voler (ordinateur non verrouillé, réseau Wi-Fi non crypté comme McDo ou Eduspot)...

Fonctionnement des sessions :

  1. Création d’une session.
  2. Création des variables session.
  3. Manipulation des variables.
  4. Fermeture de la session.

Note

La fermeture de la session peut être explicitement demandée où s’exécute automatiquement à la fermeture du navigateur, ou après un délai d’expiration (“timeout”).

Création d’une session§

La variable session $_SESSION est accessible n’importe où dans le code à condition qu’on aie préalablement fait appel à la fonction session_start(). Les variables de session s’instancient comme des champs du tableau associatif $_SESSION. Exemple :

<?php
  session_start();
  ...
  $_SESSION['champ1'] = 'chaine';
  $_SESSION['champ2'] = 42;
?>

Avertissement

session_start() doit être appellée avant toute sortie.

Utilisation des variables de session§

Toutes les variables de session qui ont prélablement été intitialisées dans des pages consultées par le client sont accessibles sur les autres pages. Il suffit de faire appel à la fonction de démarrage de la session.

<?php
  session_start();
  ...
  echo $_SESSION['champ1'];
?>

Astuce

Les variables de session sont utiles en complément d’un système d’authentification, afin de stocker des informations de connexion de l’utilisateur.

Fermeture d’une session§

La variable $_SESSION est automatiquement détruite après un délai d’expiration, ou à la fermeture du client.

Dans certains cas, il est nécessaire de fermer la session depuis le code (c’est le cas par exemple d’un bouton “Déconnexion” pour des pages à accès restreint).

La fermeture de la session s’effectue comme suit :

<?php
  ...
  session_destroy();
?>

Récapitulatif : Les variables superglobales§

Liste des variables superglobales§

Les variables superglobales sont des variables créées et instantiées par PHP.

Parmi les variables superglobales, on retrouve :

  • $_GET : données envoyées en paramètres dans l’URL
  • $_POST : données envoyées dans la requête HTTP
  • $_FILES : fichiers envoyés par un formulaire
  • $_SERVER : variables d’exécution du serveur
  • $_ENV : variables d’environnement du serveur
  • $_SESSION : variables de session
  • $_COOKIE : valeurs des cookies enregistrés sur le client

Note

Un exemple utile de variable serveur : $_SERVER['REMOTE_ADDR'] contient l’adresse IP du client qui cherche à consulter la page.

Avertissement

$_GET, $_POST, $_COOKIE et certaines variables de $_SERVER comme $_SERVER['HTTP_REFERER'] proviennent de l’utilisateur, il faut donc absolument les contrôler.

Lire et écrire dans un fichier§

Ouvrir et lire un fichier§

PHP embarque des fonctions très utiles pour ouvrir fopen(), lire fgetc()/fgets() et fermer fclose() un fichier.

Le protocole de lecture est en trois étapes :

  1. Ouverture du fichier
  2. Lecture
  3. Fermeture

Avertissement

Lors de l’ouverture avec fopen(), PHP bloque l’accès au fichier aux autres tant qu’il n’est pas libéré par fclose().

Exemple de lecture ligne par ligne :

<?php
 $fichier = fopen('fichier.txt', 'r'); // en lecture seule
 if ($fichier != NULL)
 {
   $ligne = fgets($fichier);
   while($ligne)
   {
     ... // traitement de la ligne
     $ligne = fgets($fichier);
   }
   fclose($fichier);
 }
?>

Note

Le ‘r’ signifie que le fichier est ouvert en lecture. Voir la documentation pour les autres modes.

Ecrire dans un fichier§

Pour écrire dans un fichier, il est utile de savoir modifier le curseur. Il indique la position courante de la lecture/écriture dans le fichier.

Le curseur se déplace avec la fonction fseek() et l’écriture est réalisée par fputs().

La fonction fseek() ne fonctionne qu’avec le mode d’écriture ‘r+’ ou ‘w’. Dans le cas du mode ‘a+’ (lecture seule + pas d’écrasement), les nouvelles données seront toujours écrites à la fin.

Exemple d’écriture au début du fichier :

<?php
 $fichier = fopen('fichier.txt', 'r+');
 if ($fichier != NULL)
 {
   fseek($fichier, 0);
   fputs($fichier, 'nouvelles données');
   fclose($fichier);
 }
?>

Bonnes pratiques§

Guard Clauses§

<?php
  // Peu lisible...
  function check($input)
  {
    if (condition1($input))
    {
      if (condition2($input))
        return calcul($input);
      else
        return 2;
    }
    else
      return 1;
  }
?>
<?php
  // Plus lisible !
  function check($input)
  {
    if (!condition1($input))
      return 1;
    if (!condition2($input))
      return 2;
    return calcul($input);
  }
?>

En savoir plus

... (et si la valeur de retour est la même) ...

Projet§

v2.0§

On veut permettre aux utilisateurs loggés de voter pour un film.

  1. Ajoutez une table User à la base de données:
    • user (id, login, pwd, email).
    • Implémentez un système de connexion (une page Inscription, une page Connexion)
    • Vous utiliserez les sessions pour stocker les informations de connexion
  2. Ajouter une table Vote (table d’association : movie_id, user_id).
    • Ajouter une page permettant à un utilisateur loggé de voter pour un film
    • Ajouter le nombre de votes dans le détail d’un film
  3. Bonus : hash du mot de passe, vérif syntaxe e-mail...