Hi everyone On Wed, Jul 2, 2025 at 9:58 PM Gina P. Banyard <intern...@gpb.moe> wrote: > > It is this time of year again where we proposed a list of deprecations to add > in PHP 8.5: > > https://wiki.php.net/rfc/deprecations_php_8_5
Thanks for the bulk RFC. Some thoughts. > Deprecate __construct() and __destruct() in interfaces While __construct() is tied to the new expression (at least unless instantiated through ReflectionClass::newInstanceWithoutConstructor()), factories creating instances from class names may still need to check for constructor compatibility. This is much easier achieved through an interface than it is through reflection. With an interface: interface I { public function __construct(string $a, string $b); } function some_factory(string $class) { if (!is_a($class, I::class)) { throw new InvalidArgumentException(); } return new $class('foo', 'bar'); } Without an interface: function some_factory(string $class) { $reflection = new ReflectionClass($class); $constructor = $reflection->getConstructor(); if (!$constructor || !$constructor->isPublic()) { throw new InvalidArgumentException(); } $params = $constructor->getParameters(); if (count($params) !== 2 || $params[0]->getType()->getName() !== 'string' || $params[1]->getType()->getName() !== 'string') { throw new InvalidArgumentException(); } return $class('foo', ['bar']); } This implementation is much more complex, and incorrect in multiple ways. 1. We could have more than 2 params, with them being optional. 2. We could use variadics, i.e. function __construct(string ...$s), which is completely valid. 3. Since parameter types are contravariant, they may be substituted with union types, mixed, or just completely omitted. Also note that while LSP for __construct() is not enforced for class inheritance, it is for interfaces, even across multiple class hierarchy levels. Maybe there is some issue I'm missing. But if not, I'm not in favor of deprecating/dropping this feature. > Deprecate using values of type null and bool as array offsets and when > calling array_key_exists() The introduction section also lists float as a type to be deprecated in array offsets: > Deprecate using values of type null, bool, and float as array offsets and > when calling array_key_exists() Floats used as array offsets that lose precision already emit a warning. Can you confirm that floats used as array offsets that do not lose precision will not start emitting a deprecation? > Deprecate ReflectionClass::getConstant() for missing constants I don't have strong opinions on this change. However, ReflectionProperty::getDefaultValue() suffers from a very similar issue, except that it returns null rather than false (https://3v4l.org/G2R3l). It would make sense to avoid more inconsistencies. For example, ReflectionParameter::getDefaultValue() does throw if the parameter has no default value. > Deprecate ArrayObject and ArrayIterator with objects Just to add another issue to the list: It can also change readonly properties of internal classes that the engine does not expect to ever change. For example, Enum::$name and Enum::$value. This can break internal logic assumptions (e.g. hard-coded switch cases to handle internal enums by name) and cause memory corruption. The same goes for non-readonly properties guarded with the internal equivalent of __set(). > Deprecate passing spl_autoload_call() to spl_autoload_unregister() Is such a check actually useful? We can prevent spl_autoload_unregister(spl_autoload_call(...)), but we can't prevent spl_autoload_unregister(fn($c) => spl_autoload_call($c)). It seems very unlikely for this to happen accidentally, and excluding all functions that don't make sense to pass is not feasible for obvious reasons. But I don't care too much. Ilija