A destructor is the opposite of a constructor. PHP calls __destruct() when an object is about to be removed from memory.
<?php
class Connection
{
public function __construct(private string $name)
{
echo "Opening {$this->name}\n";
}
public function __destruct()
{
echo "Closing {$this->name}\n";
}
}
$a = new Connection("A");
echo "Doing work\n";
unset($a); // the object is destroyed here
echo "After unset\n";
Opening A
Doing work
Closing A
After unset
When is it called?
- When the last reference to the object disappears (
unset(), assigningnull, or a variable going out of scope). - When the script ends, for objects that still exist.
<?php
class Note
{
public function __construct(private string $text) {}
public function __destruct()
{
echo "Bye, {$this->text}\n";
}
}
function make(): void
{
$n = new Note("local");
echo "Inside function\n";
} // $n is destroyed here
make();
echo "End of script\n";
$later = new Note("global");
Inside function
Bye, local
End of script
Bye, global
What to use it for
- Closing a file or connection that the object opened.
- Releasing a lock.
What not to do
- Do not rely on it for important work. If the script crashes or is killed, the destructor may not run. Save data explicitly, not in a destructor.
- Do not throw exceptions from it.
- Do not put slow code in it. It runs at the end of the request.
Explicit close methods are better
For resources, give the class a close() method and call it yourself, ideally inside finally.
<?php
class Logger
{
private $handle;
public function __construct(string $file)
{
$this->handle = fopen($file, "a");
}
public function write(string $message): void
{
fwrite($this->handle, $message . PHP_EOL);
}
public function close(): void
{
fclose($this->handle);
}
}
$logger = new Logger("run.log");
try {
$logger->write("Started");
} finally {
$logger->close();
}
echo "Done";
Done
PHP cleans up for you
PHP closes files and frees memory at the end of each request. Destructors are rarely needed in web code, so you will see few of them in real projects.