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);
This entry was posted in PHP. Bookmark the permalink.

7 Responses to Attention au contexte d’exécution des destructeurs

  1. stopher says:

    Intéressant ,
    Il fallait le trouver :-)

    Ch.

  2. Seza says:

    Logique mais fallait le trouver !

  3. Un élève says:

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

  4. Hervé says:

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

  5. Revlis says:

    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 says:

    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 says:

    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.