Constructors & Destructors
Creating an object and then setting its properties one by one, as the earlier pages did, leaves a window where the object exists but is not fully set up yet. A constructor closes that window: it is a special method that runs automatically the instant an object is created, so the object is guaranteed to be complete and valid from its very first usable moment. PHP also offers the opposite —a destructor that runs when an object goes away — though it is needed far less often than you might expect coming from other languages.
__construct(): initializing an object
A method named __construct() (two leading underscores) is called automatically by new, with whatever arguments you pass to new forwarded straight to it. This replaces the "create it, then set every property by hand" pattern from earlier pages with a single guaranteed step.
Product with a constructor
<?php
class Product
{
public string $name;
public float $price;
private float $taxRate;
public function __construct(string $name, float $price, float $taxRate = 0.08)
{
$this->name = $name;
$this->price = $price;
$this->taxRate = $taxRate;
}
public function getTaxedPrice(): float
{
return round($this->price * (1 + $this->taxRate), 2);
}
}
$product = new Product('Wireless Mouse', 25.00);
echo $product->name . ': $' . $product->getTaxedPrice() . "\n";Wireless Mouse: $27
There is no way to end up with a Product missing its name or price — the constructor's parameter list enforces what is required ($name, $price) and what has a sensible fallback ($taxRate, defaulting to 0.08). Any validation that belongs to "is this object even valid" also belongs here; you could, for instance, throw an exception in the constructor if $price were negative.
A quick note on constructor property promotion
The constructor above repeats each property name three times: once in the property declaration, once in the parameter list, and once in the assignment. PHP 8 introduced constructor property promotion, a shorthand that collapses all three into the parameter list itself. It is purely a syntax convenience over exactly what you see above, and it is covered in full in its own page later in this course — for now, just recognize the name if you see it mentioned.
__destruct(): cleanup when an object goes away
A method named __destruct() runs automatically when an object is destroyed. "Destroyed" can mean several things: the script reaches its end, the object's variable goes out of scope with nothing else referencing it, its reference count drops to zero some other way, or you explicitly call unset() on the only remaining reference to it.
Watching a destructor fire
<?php
class Product
{
public string $name;
public function __construct(string $name)
{
$this->name = $name;
echo "Created: {$this->name}\n";
}
public function __destruct()
{
echo "Destroyed: {$this->name}\n";
}
}
function makeTemporaryProduct(): void
{
$product = new Product('Temporary Widget');
echo "Using it inside the function...\n";
// $product goes out of scope when the function returns
}
makeTemporaryProduct();
echo "Function has returned.\n";
$lasting = new Product('Wireless Mouse');
unset($lasting); // forces destruction right now
echo "After unset.\n";Created: Temporary Widget Using it inside the function... Destroyed: Temporary Widget Function has returned. Created: Wireless Mouse Destroyed: Wireless Mouse After unset.
Temporary Widget was destroyed the moment makeTemporaryProduct() returned, because $product was the only reference to it and that reference went out of scope. Wireless Mouse was destroyed immediately by unset($lasting), since that removed its only remaining reference.
Why destructors matter less in PHP than in C++
If you have used a language like C++, destructors probably feel like essential, everyday tooling for releasing memory. In PHP, that role barely exists: PHP's garbage collector reclaims memory for you automatically once nothing references an object anymore, so you almost never write a destructor just to "free" something. Destructors in PHP earn their keep for a narrower job — releasing external resources the operating system is tracking on your behalf, like an open file handle, a database connection, or a network socket, where waiting for PHP's garbage collector on its own schedule might leave that resource held open longer than you want.
A destructor doing genuinely useful cleanup
<?php
class ProductExportFile
{
private string $path;
private $handle;
public function __construct(string $path)
{
$this->path = $path;
$this->handle = fopen($this->path, 'w');
}
public function write(string $line): void
{
fwrite($this->handle, $line . PHP_EOL);
}
public function __destruct()
{
fclose($this->handle);
}
}Here the destructor closes the file handle no matter how the object's lifetime ends, which is a genuinely useful safety net — as opposed to writing a __destruct() on a plain Product just to null out its properties, which the garbage collector was already going to do for free.
__construct()runs automatically whennewcreates an object, guaranteeing the object starts fully initialized.Constructor property promotion (PHP 8) is a shorthand for the declare-parameter-assign pattern; it is covered separately.
__destruct()runs when an object is destroyed: script end, going out of scope with no remaining references, or explicitunset().PHP's garbage collector already reclaims memory, so destructors are mainly for external resources like files, sockets, and database handles.