Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

moment d'intervention de __destruct

10 réponses
Avatar
Alarch
Bonjour,

lors de l'utilisation d'une classe je crée des répertoires et fichiers
temporaires, et je comptais utiliser la méthode __destruct () pour les
effacer à la fin du script.

Mais je me rends compte que les fichiers sont détruits avant la fin du
script et que mes méthodes ne peuvent donc plus utiliser les fichiers
temporaires.

Qu'est-ce qui déclenche la méthode destructeur en php 5 ?

J'ai retiré tous les unset du code (je réalise de gros calculs matriciels en
série et je fais des fichiers temporaires pour justement pouvoir détruire
de très gros tableaux que je linéarise pour ne pas saturer la mémoire).
Est-ce qu'un unset oublié pourrait causer cela ou bien le déclenchement du
destructeur est-il normalement lancé par autre chose que la fin du script ?

Cordialement,

Marc

10 réponses

Avatar
Olivier Miakinen
Bonjour,

Le 18/06/2008 23:44, Alarch a écrit :

lors de l'utilisation d'une classe je crée des répertoires et fichiers
temporaires, et je comptais utiliser la méthode __destruct () pour les
effacer à la fin du script.

Mais je me rends compte que les fichiers sont détruits avant la fin du
script et que mes méthodes ne peuvent donc plus utiliser les fichiers
temporaires.

Qu'est-ce qui déclenche la méthode destructeur en php 5 ?



D'après la doc, ceci ne peut arriver qu'à la destruction de l'objet.
En principe, et à moins d'un bug, je ne vois pas comment la méthode
__destruct pourrait avoir été appelée pour un objet si tu peux encore
utiliser des méthodes de cet objet.

Mais au fait, les méthodes qui utilisent chaque fichier font bien partie
du même objet ? Et le __destruct d'un objet ne détruit pas les fichiers
temporaires associés à d'autres objets ?

J'ai retiré tous les unset du code (je réalise de gros calculs matriciels en
série et je fais des fichiers temporaires pour justement pouvoir détruire
de très gros tableaux que je linéarise pour ne pas saturer la mémoire).
Est-ce qu'un unset oublié pourrait causer cela ou bien le déclenchement du
destructeur est-il normalement lancé par autre chose que la fin du script ?



Si tu as pu détruire un objet par unset, alors je ne vois pas comment tu
pourrais encore utiliser des méthodes de cet objet. Mais bien sûr, si tu
t'es mélangé les pinceaux entre objets tout est possible.

Si jamais les questions ci-dessus ne te permettaient pas de résoudre
tout seul le problème, alors réduis les classes au minimum montrant le
problème, et publie-les ici.

Cordialement,
--
Olivier Miakinen
Avatar
Alarch
Olivier Miakinen wrote:

Bonjour,

Le 18/06/2008 23:44, Alarch a écrit :

lors de l'utilisation d'une classe je crée des répertoires et fichiers
temporaires, et je comptais utiliser la méthode __destruct () pour les
effacer à la fin du script.

Mais je me rends compte que les fichiers sont détruits avant la fin du
script et que mes méthodes ne peuvent donc plus utiliser les fichiers
temporaires.

Qu'est-ce qui déclenche la méthode destructeur en php 5 ?



D'après la doc, ceci ne peut arriver qu'à la destruction de l'objet.
En principe, et à moins d'un bug, je ne vois pas comment la méthode
__destruct pourrait avoir été appelée pour un objet si tu peux encore
utiliser des méthodes de cet objet.



Oui c'est également ce que je pensais.

Mais au fait, les méthodes qui utilisent chaque fichier font bien partie
du même objet ? Et le __destruct d'un objet ne détruit pas les fichiers
temporaires associés à d'autres objets ?



Oui oui je ne crée qu'un seul objet. Il modélise une structure mécanique
complexe (des tribunes à gradins), et cette classe fait seulement appel à
des classes statiques fournissant des méthodes statiques de calcul (comme
une implémentation de la méthode de Gauss pour la résolution de systèmes de
n équations à n inconnues).
[snip]
Si tu as pu détruire un objet par unset, alors je ne vois pas comment tu
pourrais encore utiliser des méthodes de cet objet. Mais bien sûr, si tu
t'es mélangé les pinceaux entre objets tout est possible.



Non je ne fais bien entendu pas d'unset de mon objet tribune, mais
simplement des unset de gros tableaux de résultats partiels dans la méthode
constructeur qui réalise les calculs. Les unset sont internes à la classe.

Les méthodes que j'appelle ensuite ne sont que des méthodes d'affichage de
résultats sous forme de graphiques en utilisant jpgraph. Et justement, pour
ménager la mémoire, ce sont les tableaux de données des courbes (plusieurs
milliers de données par courbes) que je linéarise dans des fichiers
temporaires .

Si jamais les questions ci-dessus ne te permettaient pas de résoudre
tout seul le problème, alors réduis les classes au minimum montrant le
problème, et publie-les ici.


Cela représente beaucoup de code, je vais essayer de les synthétiser au cas
où la nuit ne m'aie pas apporté l'illumination !
Cordialement,



Merci beaucoup de cette réponse,je retourne regarder ça de près.
Avatar
Mickaël Wolff
Alarch a écrit :

Oui oui je ne crée qu'un seul objet. Il modélise une structure mécanique
complexe (des tribunes à gradins), et cette classe fait seulement appel à
des classes statiques fournissant des méthodes statiques de calcul (comme
une implémentation de la méthode de Gauss pour la résolution de systèmes de
n équations à n inconnues).



Si tu n'utilises que des méthodes et des variables statiques, jamais
ton objet ne sera détruit, puisque tu ne l'auras pas créé. Mais à mon
avis, ça montre que tu as un gros problème d'architecture, si tu
n'utilises les noms de classe que comme un espace de nom.

Les méthodes que j'appelle ensuite ne sont que des méthodes d'affichage de
résultats sous forme de graphiques en utilisant jpgraph. Et justement, pour
ménager la mémoire, ce sont les tableaux de données des courbes (plusieurs
milliers de données par courbes) que je linéarise dans des fichiers
temporaires .



Tu devrais peut-être utiliser des tables temporaires dans la base de
données ?

Cela représente beaucoup de code, je vais essayer de les synthétiser au cas
où la nuit ne m'aie pas apporté l'illumination !



Essaye de ne plus utiliser de méthodes statiques. Ça t'éviteras
certainement les problèmes que tu rencontre. Je te dis ça parce que je
crois que tu te marches sur les pieds, un peu comme quand on utilises
des variables globales.

À mon sens, les seuls cas où je vois un intérêt à utiliser des données
et fonctions membres statiques, c'est pour des méthodes d'usinage
(factory methods). Au-delà, c'est du détournement.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Alarch
Mickaël Wolff wrote:

Tu devrais peut-être utiliser des tables temporaires dans la base de
données ?



Non je ne veux pas utiliser la base de données pour ça, c'est lourd et
inutile. Et de plus j'aurai les même problèmes pour détruire mes tables
temporaires que mes fichiers avec en plus une connexion à la BDD.

Essaye de ne plus utiliser de méthodes statiques. Ça t'éviteras
certainement les problèmes que tu rencontre. Je te dis ça parce que je
crois que tu te marches sur les pieds, un peu comme quand on utilises
des variables globales.



Les méthodes statiques n'y sont pour rien, elles n'interviennent que comme
des fonctions pour des calculs. La classe centrale est bel et bien
instanciée elle, mais ce qui se passe c'est tout bêtement que l'utilisation
des classes jpgraph se fait de la façon suivante : on appelle un script
php, disons toto.php, à qui on passe en paramètre le nom d'un fichier à
délinéariser qui contient les données à traiter (mes fameux fichiers). Le
script toto.php ouvre et lit le fichier de données et renvoit une image GD
du nom de toto.php.png dans mon cas.

L'appel s'écrit dans ce style :
<a href="cheminvers/toto.php?fich=nomdufichierlinearise">

Or, le temps que les appels à toto.php génèrent leurs graphiques (et il y en
a plusieurs dizaines), le script principal s'est terminé, le destructeur a
détruit les fichiers alors que les appels à toto.php ne sont pas terminés
et cherchent les fichiers qui viennent d'être effacés.

À mon sens, les seuls cas où je vois un intérêt à utiliser des données
et fonctions membres statiques, c'est pour des méthodes d'usinage
(factory methods). Au-delà, c'est du détournement.


Ça me semble intéressant même si je ne comprends pas bien le sens exacte de
tes paroles... pourrais-tu renvoyer à un article ou expliciter .

Merci
Avatar
Mickaël Wolff
Alarch a écrit :

Non je ne veux pas utiliser la base de données pour ça, c'est lourd et
inutile.



En quoi est-ce lourd ?

Et de plus j'aurai les même problèmes pour détruire mes tables
temporaires que mes fichiers



Ça dépend d'où vient le problème.

avec en plus une connexion à la BDD.



Pas nécessairement.

Les méthodes statiques n'y sont pour rien, elles n'interviennent que comme
des fonctions pour des calculs.



Mais pourquoi sont-elles statiques ?

L'appel s'écrit dans ce style :
<a href="cheminvers/toto.php?fich=nomdufichierlinearise">

Or, le temps que les appels à toto.php génèrent leurs graphiques (et il y en
a plusieurs dizaines), le script principal s'est terminé, le destructeur a
détruit les fichiers alors que les appels à toto.php ne sont pas terminés
et cherchent les fichiers qui viennent d'être effacés.



D'accord, j'ai compris. Tu as cru que le script s'arrêtait quand le
client web a récupéré tout les liens ?

Ça me semble intéressant même si je ne comprends pas bien le sens exacte de
tes paroles... pourrais-tu renvoyer à un article ou expliciter .



Je t'invites à chercher GoF Design patterns dans ton moteur de
recherche favori. Pour simplifier, les fabriques sont des méthodes
statiques destinées à permettre l'instantiation contrôlée d'objets.
Par exemple, l'implémentation d'un singleton permet d'assurer
l'unicité d'une instance. Tu as aussi l'exemple des nombres complexes,
qui peut être instancié à l'aide de coordonnées polaires ou cartésiennes
(comment le constructeur devine la nature des nombres qui lui sont
fournies ?), etc.

Mais au final, on s'en fout ici, je crois bien, puisque ton problème
transcende les processus ;)
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Alarch
Mickaël Wolff wrote:

Alarch a écrit :




Les méthodes statiques n'y sont pour rien, elles n'interviennent que
comme des fonctions pour des calculs.



Mais pourquoi sont-elles statiques ?



Ah c'est une bonne question. Peut-être est-ce une très mauvaise idée. Rien
de ce que font ces méthodes qui ne pourrait être fait par de bêtes
fonctions. Il s'agit de remplir des matrices et les résoudres par la
méthode du pivot de Gauss pour l'essentiel. Je n'ai pas vraiment besoin
d'un objet instancié car je n'ai pas à ce niveau de contexte à maintenir.
La seule raison était pour moi de regrouper un corpus de fonctions
utilisées pour résoudre un problème, avoir ces fonctions regroupées sous un
nom commun avec des appels genre pivotGauss::calculForcesAuxAppuis(
$tableau_d_abscisses) ce qui me permet d'avoir dans le tas des fonctions
avec un nom très banal qui peut se retrouver ailleurs sans risquer l'alerte
de la double définition. En gros je regroupe toutes les fonctions un peu
spécifiques qui marchent ensemble dans une classe statique qui l'isole du
reste du monde.

Est-ce légitime ou bien un crime de lèse POO ?

D'accord, j'ai compris. Tu as cru que le script s'arrêtait quand le
client web a récupéré tout les liens ?



Oui exactement j'ai cru que c'était le script appelant qui menait la danse.
En fait il fait son boulot, dont lancer les liens de création de graphiques,
puis termine son affaire sans autre soucis et la classe lance légitimement
son destructeur une fois le boulot fait.

A la réflexion mon raisonnement était idiot, si je fais appel à des liens
externes longs à charger (ce qui est le cas, créer les graphiques n'est pas
économe de ressources), aucune raison que tout s'arrête à cause d'eux.

Je t'invites à chercher GoF Design patterns dans ton moteur de
recherche favori.


[snip]
Mais au final, on s'en fout ici, je crois bien, puisque ton problème
transcende les processus ;)



Oui mais ça n'empêche pas de se cultiver quand même ;-)
Avatar
Mickaël Wolff
Alarch a écrit :

Ah c'est une bonne question. Peut-être est-ce une très mauvaise idée. Rien
de ce que font ces méthodes qui ne pourrait être fait par de bêtes
fonctions. Il s'agit de remplir des matrices et les résoudres par la
méthode du pivot de Gauss pour l'essentiel. Je n'ai pas vraiment besoin
d'un objet instancié car je n'ai pas à ce niveau de contexte à maintenir.



Dans l'absolu, les objets n'ont pas pour but de fournir un contexte,
mais plutôt de permettre l'isolation des données et de leur manipulation.

La seule raison était pour moi de regrouper un corpus de fonctions
utilisées pour résoudre un problème, avoir ces fonctions regroupées sous un
nom commun avec des appels genre pivotGauss::calculForcesAuxAppuis(
$tableau_d_abscisses) ce qui me permet d'avoir dans le tas des fonctions
avec un nom très banal qui peut se retrouver ailleurs sans risquer l'alerte
de la double définition. En gros je regroupe toutes les fonctions un peu
spécifiques qui marchent ensemble dans une classe statique qui l'isole du
reste du monde.



Oui, en fait tu as détourné les classes pour en faire des namespace
procéduraux :)

Est-ce légitime ou bien un crime de lèse POO ?



Ben oui, sauvage ;) Mais surtout, si ça se trouve tu passes à côté
d'une facilité que t'offrirait une approche objet. Par exemple, on peut
imaginer une classe qui s'utiliserait comme ça :

$cloche = new matrice ;
$cloche->ajouterLigne(array(...)) ;
$cloche->ajouterLigne(array(...)) ;
if($cloche->estResolvable())
while($cloche->reduire()) /* pas forcément pertinent */ ;

Ce qui veut dire que tu pourrais gérer plusieurs matrices à la fois,
et surtout que tu pourrais surchargé ta matrice en fournissant un
algorithme plus adapté, sans que tu n'ai à aller ensuite changer chaque
appel à ta fonction statique).

A la réflexion mon raisonnement était idiot, si je fais appel à des liens
externes longs à charger (ce qui est le cas, créer les graphiques n'est pas
économe de ressources), aucune raison que tout s'arrête à cause d'eux.



C'est une confusion de débutant, pas la peine de considérer que c'est
idiot. Je crois me souvenir de misconceptions bien pire dans une autre vie !

Oui mais ça n'empêche pas de se cultiver quand même ;-)



Certes.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Alarch
Mickaël Wolff wrote:

[snip]
Dans l'absolu, les objets n'ont pas pour but de fournir un contexte,
mais plutôt de permettre l'isolation des données et de leur manipulation.



Oui, c'est bien ce que j'ai cru comprendre en lisant la bonne parole de
l'orienté objet. Mais il faut bien dire que je ne suis pas tombé dans
l'objet étant petit... Je date un peu moi. C'est loin d'être un réflexe et
il faut vraiment que je fasse un effort pour m'arracher a la vieille
programmation procédurale. Pour une fois que j'essaye de faire presque rien
que de l'objet ! :-(



Oui, en fait tu as détourné les classes pour en faire des namespace
procéduraux :)



Dont acte... mais promis juré je l'ai fait avec la même innocence que
Monsieur Jourdain faisant de la prose... je savions pas ;-) (mais c'est
joli namespace précédural, même qu'il me semble comprendre ce que ça veut
dire).

Il eusse donc fallu que je m'astreignasse plutôt à créer des noms de
fonction genre truc.machin.turlututu pour la différencier du turlututu de
bidule.chose.turlututu ? (un espace de noms quoi).

Est-ce légitime ou bien un crime de lèse POO ?



Ben oui, sauvage ;)



Je m'en flagelle encore...!!

Mais surtout, si ça se trouve tu passes à côté
d'une facilité que t'offrirait une approche objet. Par exemple, on peut
imaginer une classe qui s'utiliserait comme ça :

$cloche = new matrice ;
$cloche->ajouterLigne(array(...)) ;
$cloche->ajouterLigne(array(...)) ;
if($cloche->estResolvable())
while($cloche->reduire()) /* pas forcément pertinent */ ;

Ce qui veut dire que tu pourrais gérer plusieurs matrices à la fois,
et surtout que tu pourrais surchargé ta matrice en fournissant un
algorithme plus adapté, sans que tu n'ai à aller ensuite changer chaque
appel à ta fonction statique).



Oui certes, mais ces classes statiques sont vraiment de bas niveau, je n'ai
pas lieu de les surcharger. Mais je suis d'accord sur le principe
(d'ailleurs j'ai une classe statique qui hérite d'une autre classe
statique... ça doit encore être une horreur en POO ça ! Mais pourquoi Php
me laisse-t-il faire aussi)


C'est une confusion de débutant, pas la peine de considérer que c'est
idiot. Je crois me souvenir de misconceptions bien pire dans une autre vie
!



Ben oui moi aussi j'ai fait plus bête encore, mais ce que tu dis
m'inquiète... la retraite risque de me trouver encore débutant ! Quelle
horreur. :-o

Enfin en tout cas merci de toutes ces considérations, mine de rien c'est
rare de pouvoir parler légèrement de problèmes de fond. Un jour je finirai
bien par maîtriser cette foutue POO non mais...
Avatar
Mickaël Wolff
Alarch a écrit :
Il eusse donc fallu que je m'astreignasse plutôt à créer des noms de
fonction genre truc.machin.turlututu pour la différencier du turlututu de
bidule.chose.turlututu ? (un espace de noms quoi).



J'ai pas compris.

Oui certes, mais ces classes statiques sont vraiment de bas niveau, je n'ai
pas lieu de les surcharger. Mais je suis d'accord sur le principe
(d'ailleurs j'ai une classe statique qui hérite d'une autre classe
statique... ça doit encore être une horreur en POO ça ! Mais pourquoi Php
me laisse-t-il faire aussi)



Ah non, on accuse pas le langage ! Qu'on puisse dériver d'une classe
contenant des fonctions membres statique n'est pas une hérésie.

Ben oui moi aussi j'ai fait plus bête encore, mais ce que tu dis
m'inquiète... la retraite risque de me trouver encore débutant ! Quelle
horreur. :-o



Tu auras une retraite, toi ;)

Enfin en tout cas merci de toutes ces considérations, mine de rien c'est
rare de pouvoir parler légèrement de problèmes de fond. Un jour je finirai
bien par maîtriser cette foutue POO non mais...



J'y arriverais aussi un jour :-D

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Alarch
Mickaël Wolff wrote:

Alarch a écrit :
Il eusse donc fallu que je m'astreignasse plutôt à créer des noms de
fonction genre truc.machin.turlututu pour la différencier du turlututu de
bidule.chose.turlututu ? (un espace de noms quoi).



J'ai pas compris.


Ah ? c'est pas clair ? :-)

J'ai vu au passage que dans le dernier php il existe une notion de
namespace, mais on verra ça plus tard.


Ah non, on accuse pas le langage ! Qu'on puisse dériver d'une classe
contenant des fonctions membres statique n'est pas une hérésie.



Bon tant mieux alors.

Ben oui moi aussi j'ai fait plus bête encore, mais ce que tu dis
m'inquiète... la retraite risque de me trouver encore débutant ! Quelle
horreur. :-o



Tu auras une retraite, toi ;)



Hum j'aurais plutôt dû dire "l'âge de la retraite", parce que pour ce qui
est de la retraite je doute fort...

Bon je retourne à mes membres statiques... ;-)