Attention au contexte d’exécution des destructeurs

Lors d’un exercice en Licence Professionnelle Informatique Web Développeur à l’INSSET de Saint-Quentin, mes élèves ont constaté un comportement étrange avec le destructeur d’une classe. Voici un exemple minimal du problème :

<?php class Exemple { 	public function __destruct() 	{ 		file_put_contents('log.txt', 'Test'); 	} } $exemple = new Exemple();

Ce code ne pose a priori pas de problème et pourtant si vous l’exécutez avec Apache sur Unix vous risquez d’avoir des problèmes de droit d’écriture :

Warning: file_put_contents(log.txt) [function.file-put-contents]: failed to open stream: Permission denied in /var/www/test/destruct.php on line 6

En fait l’explication est aussi étonnante que simple et comme souvent on la trouve dans la documentation de PHP : lors de la phase de clôture d’un script, le contexte peut changer sur certains SAPI dont Apache.

Cela veux dire que notre instance étant détruite implicitement lors de la clôture du script, PHP ne va pas essayer de créer le fichier, dont le chemin est relatif, dans le même répertoire que le script mais dans un autre répertoire où il n’a pas forcément le droit d’écrire.

Pour contourner ce problème, il suffit soit de donner au fichier un chemin absolu pour le fichier, soit de détruire explicitement l’instance afin que cela se fasse avant la phase de clôture du script :

$exemple = null

ou

unset($exemple);
Ce contenu a été publié dans PHP. Vous pouvez le mettre en favoris avec ce permalien.

7 réponses à Attention au contexte d’exécution des destructeurs

  1. stopher dit :

    Intéressant ,
    Il fallait le trouver 🙂

    Ch.

  2. Seza dit :

    Logique mais fallait le trouver !

  3. Un élève dit :

    C’est vrai qu’on a mis du temps a trouvé le problème !

  4. Hervé dit :

    D’une manière générale, tous les chemins devraient être pleinement qualifiés

  5. Revlis dit :

    Tout a fait d’accord avec Hervé, que ce soit avec __DIR__ de php 5.3 ou dirname(__FILE__) des version antérieur, il est aisé de récupérer le chemin absolue d’un dossier de travail et travailler plus sereinement.

  6. Martin dit :

    J’approuve complètement la bonne pratique sur l’utilisation de chemins complets.

    Ceci mis à part c’est toujours intérressant de comprendre les différents comportements de PHP.

  7. Méthylbro dit :

    Cependant le problème peut persister dans le cas ou il resterait des références sur cet objet.

    En php5 la manipulation d’objet se faisant par référence le cas suivant poserais encore problèmes :

    $exemple = new Exemple();
    // …
    $exemple2 = $exemple;
    unset($exemple);

    C’est donc Hervé qui est dans le vrai ; tous les chemins devraient être pleinement qualifiés.

Les commentaires sont fermés.