Comment détruire un objet?

120

Autant que je sache (ce qui est très peu), il y a deux façons, étant donné:

$var = new object()

Ensuite:

// Method 1: Set to null
$var = null;
// Method 2: Unset 
unset($var); 

Une autre meilleure méthode? Suis-je en train de fendre les cheveux ici?

PandémoniumSyndiquer
la source

Réponses:

152

Vous cherchez unset() .

Mais gardez à l'esprit que vous ne pouvez pas détruire explicitement un objet.

Il restera là, cependant si vous désactivez l'objet et que votre script pousse PHP dans les limites de la mémoire, les objets inutiles seront récupérés. J'irais avec unset()(plutôt que de le définir sur null) car il semble avoir de meilleures performances (non testé mais documenté sur un des commentaires du manuel officiel de PHP).

Cela dit, gardez à l'esprit que PHP détruit toujours les objets dès que la page est servie. Cela ne devrait donc être nécessaire que sur des boucles très longues et / ou des pages très intensives.

Frankie
la source
1
Donc Frankie, je viens du C ++, où quand on utilise newune fois, alors on doit utiliser deleteune fois. Ce n'est pas vrai en PHP? Il y a un garbage collection automatique lorsque l'objet n'est plus nécessaire?
gsamaras du
3
@gsamaras c'est vrai. Vous pouvez également avoir des fuites, cependant, et vous devriez en savoir plus sur le GC de php si vous faites des démons ou similaires. Dans la majorité des sites, la demande est si courte qu'elle n'a pas d'importance. php.net/manual/en/features.gc.refcounting-basics.php
Frankie
unset()Supprime- t-il la référence à l'objet?
Yousha Aleayoub
9

Un article pratique expliquant plusieurs malentendus à ce sujet:

N'appelez pas explicitement le destructeur

Cela couvre plusieurs idées fausses sur le fonctionnement du destructeur. L'appeler explicitement ne détruira pas réellement votre variable, selon la doc PHP5:

PHP 5 introduit un concept de destructeur similaire à celui des autres langages orientés objet, tels que C ++. La méthode destructor sera appelée dès qu'il n'y aura pas d'autres références à un objet particulier, ou dans n'importe quel ordre pendant la séquence d'arrêt.

Le message ci-dessus indique que la définition de la variable sur null peut fonctionner dans certains cas, tant que rien d'autre ne pointe vers la mémoire allouée.

Sturrockad
la source
2

Réponse courte: les deux sont nécessaires.

J'ai l'impression que la bonne réponse a été donnée mais de manière minimale. Ouais généralement unset () est le meilleur pour la "vitesse", mais si vous voulez récupérer de la mémoire immédiatement (au prix du processeur), vous devez utiliser null.

Comme d'autres l'ont mentionné, définir sur null ne signifie pas que tout est récupéré, vous pouvez avoir des objets de mémoire partagée (non clonés) qui empêcheront la destruction de l'objet. De plus, comme d'autres l'ont dit, vous ne pouvez pas «détruire» les objets explicitement de toute façon, vous ne devriez donc pas essayer de le faire de toute façon.

Vous devrez déterminer ce qui vous convient le mieux. Vous pouvez également utiliser __destruct () pour un objet qui sera appelé sur unset ou null mais il doit être utilisé avec précaution et comme d'autres l'ont dit, ne jamais être appelé directement!

voir:

http://www.stoimen.com/blog/2011/11/14/php-dont-call-the-destructor-explicitly/

Quelle est la différence entre l'affectation de NULL et unset?

Mike Q
la source
0

Ceci est une simple preuve que vous ne pouvez pas détruire un objet, vous ne pouvez détruire qu'un lien vers celui-ci.

$var = (object)['a'=>1];
$var2 = $var;
$var2->a = 2;
unset($var2);
echo $var->a;

Retour

2

Voyez-le en action ici: https://eval.in/1054130

Yevgeniy Afanasyev
la source
3
Bien, vous avez détruit $var2ce qui était une référence $var. Maintenant, vous détruisez $varégalement et, en supposant qu'il n'y a pas d'autres références sur l'objet, vous avez terminé.
i336_
4
Vous ne détruisez pas un objet, vous détruisez un pointeur vers l'objet. C'est une grande différence.
Yevgeniy Afanasyev
1
Dans d'autres langues, vous pouvez détruire un objet et tous les autres pointeurs vous donneront des exceptions ou des déchets, mais ce n'est pas un cas pour php
Yevgeniy Afanasyev
1
Vous ne pouvez pas détruire. S'il n'y a aucune référence contenant l'objet, l'objet est prêt à être collecté par le garbage collector. Et vous ne pouvez pas forcer à exécuter le garbage collector.
Daniel
0

Peut être dans une situation où vous créez un nouvel objet mysqli.

$MyConnection = new mysqli($hn, $un, $pw, $db);

mais même après avoir fermé l'objet

$MyConnection->close();

si vous utilisez print_r()pour vérifier le contenu de $MyConnection, vous obtiendrez une erreur comme ci-dessous:

Error:
mysqli Object

Warning: print_r(): Property access is not allowed yet in /path/to/program on line ..
( [affected_rows] => [client_info] => [client_version] =>.................)

dans ce cas, vous ne pouvez pas utiliser unlink()car unlink()nécessitera une chaîne de nom de chemin, mais dans ce cas, il $MyConnections'agit d'un objet.

Vous avez donc un autre choix de définir sa valeur sur null:

$MyConnection = null;

maintenant les choses vont bien, comme vous vous y attendiez. Vous n'avez aucun contenu dans la variable $MyConnectionet vous avez déjà nettoyé l'objet mysqli.

Il est recommandé de fermer l'objet avant de définir la valeur de votre variable sur null.

Subrat Kumar Palhar
la source
-7

J'irais avec unset car cela pourrait donner au ramasse-miettes un meilleur indice afin que la mémoire puisse être à nouveau disponible plus tôt. Veillez à ce que toutes les choses vers lesquelles l'objet pointe soit aient d'autres références ou soient annulées en premier, sinon vous devrez vraiment attendre le ramasse-miettes car il n'y aurait alors aucun descripteur.

hackartiste
la source
16
À moins que vous n'ayez réellement des sources pour sauvegarder vos réponses, vous ne devriez probablement pas publier ce que vous pensez «pourrait» arriver. Ce n'est pas utile et conduit à ce que ce genre de désinformation soit considéré comme une vérité et répété.
meagar
1
@meagar c'est la raison exacte pour laquelle j'ai lié à la page de manuel officielle où, dans les commentaires, il y a un exemple de test comparant unset () à null.
Frankie