PHP 8.4 added property hooks, which let you run code when a property is read or written. Hooks weren't allowed on readonly properties, though. This RFC from Larry Garfield and Nick Sdot proposed allowing them on backed readonly properties, meaning properties that actually store a value. It had two parts, with separate votes for get hooks and set hooks.

Why they wanted it

The authors argue that readonly really means "write once," not "this value never changes." A readonly property can hold an object that is still mutable, and __get() can already return a different value on every call. By that reasoning, a get hook wouldn't break any promise PHP makes today.

A get hook would let ORMs and proxies lazy-load a single property the first time you access it. A set hook would let you validate a value before it's stored. Here is the RFC's example:

readonly class PositivePoint
{
    public function __construct(
        public int $x { set => $value > 0 ? $value : throw new \Exception(); },
        public int $y { set => $value > 0 ? $value : throw new \Exception(); },
    ) {}
}

$p = new PositivePoint(4, 5);
$p->x = 1; // Still fails the readonly check, as today.

That code isn't allowed in PHP 8.4. The authors said it matters more with the new clone() syntax in PHP 8.5, which can change readonly properties while copying an object and skips any checks in the constructor. A set hook would still run and catch a bad value.

What it means for existing code

Nothing would break. The RFC says no code that works today would stop working.

The authors also considered and rejected two other ideas: caching a get hook's result after the first call, and adding a new init hook. Both were left out.

The vote

Declined. Both parts needed a two-thirds majority, and both fell short. get hooks lost 5 to 21, and set hooks got 13 in favor and 9 against, a majority but not two-thirds. The vote ran from July 20 to August 3, 2025, and the RFC had been aimed at PHP 8.5.