Hi everyone
On Wed, Jul 2, 2025 at 9:58 PM Gina P. Banyard <internals@gpb.moe> wrote:
It is this time of year again where we proposed a list of deprecations to add in PHP 8.5:
PHP: 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
(Online PHP editor | output for 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