unserialize creates an object without calling the constructor and then writes the properties, which is precisely the thing readonly forbids. Native serialisation is allowed by an explicit carve-out…
Hydrating an enum from a request parameter with from() produced an uncaught ValueError on the first malformed input, which was about nine minutes after deploy. The two methods…
__set is only called for inaccessible or undefined properties, so declaring the property you meant to intercept disables the magic silently. The private case is the one that…
A constructor with an optional dependency needed a null default and a line of null-coalescing, in every class that had one. The exclusion of property defaults is the…
8.1, and a keyword that removes a getter per property. Forty value objects, each with private fields and public accessors that existed only to prevent writes.
A pure enum has cases and nothing behind them, which makes it useless for a database column and exactly right for a distinction that only exists inside the…
Requiring something that is both Countable and Traversable previously meant declaring an interface extending both and changing every implementing class. The restriction to class and interface types is…
get_object_vars respects scope, so the same call returns different arrays depending on where it is written. The scope sensitivity is documented and is nearly always encountered as a…