Como destruir um objeto?

120

Tanto quanto eu sei (o que é muito pouco), existem duas maneiras, dadas:

$var = new object()

Então:

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

Outro método melhor? Estou partindo cabelos aqui?

PandemoniumSyndicate
fonte

Respostas:

152

Você está procurando unset().

Mas leve em consideração que você não pode destruir explicitamente um objeto.

Ele permanecerá lá, no entanto, se você desarmar o objeto e seu script enviar o PHP para os limites de memória, os objetos não necessários serão coletados como lixo. Eu aceitaria unset()(em vez de configurá-lo como nulo), pois parece ter melhor desempenho (não testado, mas documentado em um dos comentários do manual oficial do PHP).

Dito isto, lembre-se de que o PHP sempre destrói os objetos assim que a página é veiculada. Portanto, isso só deve ser necessário em loops muito longos e / ou páginas intensas e pesadas.

Frankie
fonte
1
Então, Frankie, eu venho de C ++, onde quando usamos newuma vez, devemos usar deleteuma vez. Isso não é verdade em PHP? Há coleta automática de lixo quando o objeto não é mais necessário?
gsamaras
3
@gsamaras isso é verdade. Você também pode ter vazamentos, e deve ler mais no GC do php se estiver fazendo daemons ou similares. Na maioria dos sites, a solicitação é tão curta que não importa. php.net/manual/en/features.gc.refcounting-basics.php #
Frankie
Será que unset()remove a referência para o objeto?
Yousha Aleayoub
9

Um post útil que explica vários mal-entendidos sobre isso:

Não ligue explicitamente para o destruidor

Isso cobre vários conceitos errados sobre como o destruidor funciona. Chamar explicitamente não destruirá sua variável, de acordo com o documento do PHP5:

O PHP 5 introduz um conceito destruidor semelhante ao de outras linguagens orientadas a objetos, como C ++. O método destruidor será chamado assim que não houver outras referências a um objeto específico ou em qualquer ordem durante a sequência de desligamento.

A postagem acima afirma que definir a variável como nula pode funcionar em alguns casos, desde que nada mais esteja apontando para a memória alocada.

sturrockad
fonte
2

Resposta curta: Ambos são necessários.

Eu sinto que a resposta certa foi dada, mas minimamente. Sim, geralmente o unset () é melhor para "velocidade", mas se você deseja recuperar a memória imediatamente (ao custo da CPU) deve usar nulo.

Como outros mencionados, definir como nulo não significa que tudo é recuperado, é possível ter objetos de memória compartilhada (não clonados) que impedirão a destruição do objeto. Além disso, como outros já disseram, você não pode "destruir" os objetos explicitamente de qualquer maneira, portanto não deve tentar fazê-lo.

Você precisará descobrir qual é o melhor para você. Além disso, você pode usar __destruct () para um objeto que será chamado não configurado ou nulo, mas deve ser usado com cuidado e, como outros disseram, nunca será chamado diretamente!

Vejo:

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

Qual é a diferença entre atribuir NULL e não definir?

Mike Q
fonte
0

Esta é uma prova simples de que você não pode destruir um objeto, apenas um link para ele.

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

retorna

2

Veja em ação aqui: https://eval.in/1054130

Yevgeniy Afanasyev
fonte
3
Certo, você destruiu o $var2que era uma referência $var. Agora você destrói $vartambém e, presumindo que não haja outras referências no objeto, está pronto.
i336_
4
Você não está destruindo um objeto, está destruindo um ponteiro para o objeto. É uma grande diferença.
Yevgeniy Afanasyev 16/09
1
Em outras línguas você pode destruir um objeto e todos os outros ponteiros lhe dará exceções ou lixo, mas não é um caso para php
Yevgeniy Afanasyev
1
Você não pode destruir. Se não houver referência mantendo o objeto, ele estará pronto para ser coletado pelo coletor de lixo. E você não pode forçar a execução do coletor de lixo.
22419 Daniel
0

Pode estar em uma situação em que você está criando um novo objeto mysqli.

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

mas mesmo depois de fechar o objeto

$MyConnection->close();

se você usar print_r()para verificar o conteúdo $MyConnection, receberá um erro como abaixo:

Error:
mysqli Object

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

nesse caso, você não pode usá-lo unlink()porque unlink()exigirá uma string de nome de caminho, mas nesse caso $MyConnectioné um objeto.

Então você tem outra opção de definir seu valor como nulo:

$MyConnection = null;

agora as coisas vão bem, como você esperava. Você não possui nenhum conteúdo dentro da variável $MyConnectione já limpou o objeto mysqli.

É uma prática recomendada fechar o objeto antes de definir o valor da sua variável como null.

Subrat Kumar Palhar
fonte
-7

Eu usaria o unset porque poderia dar ao coletor de lixo uma dica melhor para que a memória possa estar disponível novamente mais cedo. Cuidado para que tudo o que o objeto aponta tenha outras referências ou seja desabilitado primeiro, ou você realmente terá que esperar no coletor de lixo, pois não haveria identificadores para eles.

hackartist
fonte
16
A menos que você realmente tenha fontes para fazer backup de suas respostas, provavelmente não deve postar o que acha que "pode" acontecer. Não é útil e leva a que esse tipo de desinformação seja tomado como verdade e repetido.
meagar
1
@eagar essa é a razão exata pela qual vinculei à página do manual oficial, onde, nos comentários, há um exemplo de teste comparando unset () a null.
Frankie