Indeed, you have to be careful when using __destruct
.
This is a special function that fires when the object is about to be destroyed. When PHP calls exit
(as wp_send_json()
does), we do not control in what order PHP will destroy the objects.
So __destruct
is very dangerous when it relies on other classes. I’ve seen this causing fatals especially on PHP 5.6, which leads to errors like this:
/**
* Job destructor
*/
public function __destruct()
{
$this->logger->commit();
}
Fatal error: Uncaught Error: Call to a member function commit() on null
The Solution
Instead of:
$job = new Job;
wp_send_json($job->start());
Do:
wp_send_json((new Job)->start());
Which is the same as:
$job = new Job;
$results = $job->start();
// Trigger __destruct while we are on a known state
unset($job);
wp_send_json($results);
You have to do this when the PHP process is going to be interrupted by an exit
or a die
.
wp_send_json()
is the most notable example, as we use it a lot and it calls exit
right after echoing the JSON string. But this could apply to other functions, like wp_die()
, exit
, die
, etc.
Bottom line, just make sure that a function that uses __destruct
is destroyed if the PHP process is going to be interrupted, otherwise, this could cause issues.
Proof of concept: https://3v4l.org/GBBIV