Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A destructor in PHP is a magic method named __destruct() that is automatically invoked by the Zend Engine when an object is destroyed. This occurs immediately when an object’s reference count drops to zero via the engine’s variable management system (zval refcounting), when circular references are cleaned up by the cyclic garbage collector, or during the script’s shutdown sequence.

Syntax and Visibility

The destructor cannot accept any arguments. While typically declared with public visibility, destructors can be declared as protected or private. Restricting visibility requires that the object’s reference count drops to zero strictly within a scope where the method is accessible; otherwise, the engine will throw a visibility-related fatal error upon attempted destruction during normal execution. However, this visibility check is completely bypassed during the script shutdown phase. If an object with a private or protected destructor survives until script termination, the engine will destroy it without throwing any visibility-related fatal errors.
class ClassName {
    public function __destruct() {
        // Teardown logic executed upon object destruction
    }
}

Execution Triggers

The __destruct() method is placed onto the call stack under the following conditions:
  1. Explicit Unsetting: The unset() language construct is called on the variable holding the last reference to the object, reducing the object’s reference count to zero.
  2. Reassignment: The variable holding the last reference to the object is assigned a new value.
  3. Scope Exit: The local variable holding the last reference to the object goes out of scope.
  4. Cyclic Garbage Collection: The cyclic garbage collector (gc_collect_cycles()) identifies and cleans up unreachable objects involved in circular references.
  5. Script Termination: The PHP script finishes execution, triggering the shutdown phase where all remaining objects are destroyed in an undefined order.
class InstanceTracker {
    public function __destruct() {
        echo "Destructor invoked.\n";
    }
}

$obj = new InstanceTracker();
unset($obj); // Triggers __destruct() immediately via zval refcounting

$obj2 = new InstanceTracker();
$obj2 = null; // Triggers __destruct() immediately due to reassignment

Inheritance Rules

PHP does not implicitly call the parent class’s destructor if the child class defines its own __destruct() method. To execute the parent’s teardown logic, the child class must explicitly invoke parent::__destruct(). If the child class does not define a destructor, it will inherit the parent’s destructor like any standard method.
class ParentClass {
    public function __destruct() {
        echo "Parent destroyed.\n";
    }
}

class ChildClass extends ParentClass {
    public function __destruct() {
        echo "Child destroyed.\n";
        parent::__destruct(); // Explicit invocation required
    }
}

Technical Constraints and Behavior

  • Argument Signature: Defining __destruct() with parameters will result in a fatal error.
  • Exception Handling: Throwing an exception from __destruct() is permitted during normal script execution triggered by standard reference counting, but carries critical caveats:
    • If the destructor is invoked implicitly by the cyclic garbage collector (gc_collect_cycles()) during normal execution, throwing an exception can lead to fatal errors or unpredictable behavior. This is because the garbage collector can run implicitly at almost any point in the code where memory is allocated.
    • If an exception is thrown from a destructor invoked during the script shutdown phase, it results in a fatal error in all PHP versions, as the execution context lacks an active try/catch block to intercept it.
  • Shutdown Context: When a destructor is invoked during the script shutdown sequence, HTTP headers have already been sent. Relying on the current working directory or attempting to manipulate output buffers during this phase can yield unpredictable results depending on the Server API (SAPI).
  • Fatal Errors and Termination: An explicit exit() or die() call triggers the shutdown phase, executing destructors for instantiated objects. Caught exceptions trigger destructors during stack unwinding as variables go out of scope. Uncaught exceptions do not unwind the stack; they halt execution and trigger a fatal error, after which destructors are executed during the script shutdown phase. Conversely, true fatal errors (e.g., E_ERROR, E_COMPILE_ERROR, or memory limit exhaustion) immediately halt the Zend Engine and bypass destructors entirely.
Master PHP with Deep Grasping Methodology!Learn More