Alternative ways to build an object are static factories (named constructors) such as Money::fromString(); a private constructor forces callers through them. An anonymous class (PHP 7.0, readonly since 8.3) declares and instantiates a one-off class, ideal as a test double.
<?php
final class Money {
private function __construct(
public private(set) int $cents, public private(set) string $cur) {}
public static function fromString(string $s): self { // "12.50 EUR"
[$units, $hundredths, $cur] = sscanf($s, '%d.%2d %3s');
return new self($units * 100 + $hundredths, $cur);
}
}
interface Clock { public function now(): DateTimeImmutable; }
$clock = new class('2026-09-23 10:00') implements Clock {
public function __construct(private string $at) {}
public function now(): DateTimeImmutable { return new DateTimeImmutable($this->at); }
};
$m = Money::fromString('12.50 EUR');
echo "$m->cents $m->cur | ", $clock->now()->format('D H:i'), "\n";
echo strstr(get_class($clock), "\0", true), "\n"; // the name up to its NUL byte
try { new Money(1, 'USD'); } catch (Error $e) { echo $e->getMessage(), "\n"; }Output
1250 EUR | Wed 10:00 Clock@anonymous Call to private Money::__construct() from global scope
The generated name continues after the NUL byte with the file, line and a counter, so never store it. Return static from factories that subclasses should inherit (Subsection 4.9.6).