[PHP-DEV] [RFC] Deprecations for PHP 8.5

Hello internals,

It is this time of year again where we proposed a list of deprecations to add in PHP 8.5:

As a reminder, this list has been compiled over the course of the past year by various different people.

And as usual, each deprecation will be voted in isolation.

We still have a bit of time buffer, so if anyone else has any suggestions, they are free to add them to the RFC.

Some should be non-controversial, others a bit more.
If such, they might warrant their own dedicated RFC, or be dropped from the proposal altogether.

Best regards,

Gina P. Banyard

On Wed, Jul 2, 2025, at 2:56 PM, Gina P. Banyard wrote:

Hello internals,

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

As a reminder, this list has been compiled over the course of the past
year by various different people.

And as usual, each deprecation will be voted in isolation.

We still have a bit of time buffer, so if anyone else has any
suggestions, they are free to add them to the RFC.

Some should be non-controversial, others a bit more.
If such, they might warrant their own dedicated RFC, or be dropped from
the proposal altogether.

Best regards,

Gina P. Banyard

For the DB-specific PDO constants, am I correct that all of those constants and methods already have equivalents in their respective driver classes? (If so, please state that explicitly.)

Everything else seems reasonable to me at the moment.

--Larry Garfield

On Jul 2, 2025, at 4:56 PM, Gina P. Banyard <internals@gpb.moe> wrote:

Hello internals,

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

As a reminder, this list has been compiled over the course of the past year by various different people.

And as usual, each deprecation will be voted in isolation.

We still have a bit of time buffer, so if anyone else has any suggestions, they are free to add them to the RFC.

Some should be non-controversial, others a bit more.
If such, they might warrant their own dedicated RFC, or be dropped from the proposal altogether.

Best regards,

Gina P. Banyard

Thanks for reminding me I should dust off my proposal for cleaning up
ODBC driver support. Might be a good idea to put it to a vote...

On Wed, Jul 2, 2025, 21:58 Gina P. Banyard internals@gpb.moe wrote:

Hello internals,

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

As a reminder, this list has been compiled over the course of the past year by various different people.

And as usual, each deprecation will be voted in isolation.

We still have a bit of time buffer, so if anyone else has any suggestions, they are free to add them to the RFC.

Some should be non-controversial, others a bit more.
If such, they might warrant their own dedicated RFC, or be dropped from the proposal altogether.

Best regards,

Gina P. Banyard

PDO::ERRMODE_WARNING

I am ok with deprecating this mode as I cannot imagine why would anyone use it. However, can I suggest that we deprecate the silent mode too? How useful is the silent mode in PDO?

ext/filter deprecations

As much as I hate this extension, I don’t think deprecating these functions is the right choice. It’s not unheard of for someone to use filter_input without the filter parameter to avoid getting the warning on missing value. See the top comment on https://www.php.net/manual/en/function.filter-input.php#115086

Maybe we should just unbundle that whole extension?

docref_root

Can this still be used for development environment in another language? I.e. point to the manual in localized version?

Deprecate using values of type null and bool as array offsets

I can see the value in getting rid of it, but this behavior can be useful too. For example

$tally[isEnabled($name)]++;

On 2025-07-03 07:56, Gina P. Banyard wrote:

Hello internals,

Some should be non-controversial, others a bit more.
If such, they might warrant their own dedicated RFC, or be dropped from the proposal altogether.

Best regards,

Gina P. Banyard

Just skimming and saw

> Deprecate using values of type null and bool as array offsets and when calling array_key_exists()

The discussion that follows says what is wrong with null (and I agree with that), but not why bool should be deprecated as well (in fact it mentions that bool gets cast to int).

It's just that I've more than once found it self-documenting to use a bool as an array offset because I wanted to partition an array into two according to a predicate - e.g., $partition[true] contains those elements that satisfy the predicate. Especially when the question of which of those two partitions I want is itself a runtime boolean decision.

On 2 July 2025 20:56:12 BST, "Gina P. Banyard" <internals@gpb.moe> wrote:

Hello internals,

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

For FILTER_CALLBACK, I can see it being useful in the extended mode of filter_var_array, where a separate filter and options can be defined for each key in the subject array. This allows you to build up a set of filters in advance, using callbacks for advanced cases; or even to recurse into another filter_var_array call on sub-arrays.

I am not a huge fan of the filter extension, but don't see any particular reason to remove this one feature of it.

Rowan Tommins
[IMSoP]

Hi,

On Wed, Jul 2, 2025 at 10:00 PM Gina P. Banyard internals@gpb.moe wrote:

Hello internals,

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

Here are few notes on the ones that I don’t agree with:

Deprecate backticks as an alias for shell_exec

I think this might be too big BC break that might impact many scripts - would be good to see also if it impacts OSS projects. I guess it will impact even more non public code bases.

Deprecate the __sleep() and __wakeup() magic methods

I’m not sure about this one. I don’t think it’s worth it. It’s just an unnecessary BC break IMHO. I would also consider more ext/standard thing rather than language.

Deprecate the error_prepend_string and error_append_string INI directives

I think it doesn’t have a good enough reason to be deprecated and might be still used. I don’t see any problem with keeping them.

Deprecate the report_memleaks INI directive

I think this should be kept as one might not necessarily have time to fix it but still need to work reasonably with debug build so it makes sense to suppress it.

Deprecate the $http_response_header predefined variable

I think it’s too early for this. I would prefer to not deprecate it at this time because alternative is available only from 8.4…

Deprecate filter_input(), filter_input_array(), and filter_has_var()

I think those functions might be useful in some cases. I would also like to see their current usage. The case of modification of super global is not exactly a usual thing so I wouldn’t worry much about it.

Kind regards

Jakub

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

On Wed, 2 Jul 2025, Gina P. Banyard wrote:

Some should be non-controversial, others a bit more. If such, they
might warrant their own dedicated RFC, or be dropped from the proposal
altogether.

The changes to filter continue to undermine what the extension was meant
to do. The filter.default INI setting was deprecated in PHP
8.1, which was already a mistake.

The intention behind the filter extension was that admins can set a
default filter for *all* data coming in through this `filter.default`
setting as a "safe" fallback. That could/should probably even be a
filter that just makes all data ":smiling_face:" for example, to indicate you're
working with unsanitised data. (I don't think there is such a filter
though).

This fallback could then be 'circumvented' by using the
filter_input/input_array() functions, so that each of them can employ
its own unique, and useful, filter on that specific element in the
GET/POST/etc arrays.

Saying that "The filter_input() and filter_input_array() functions
operate on the original values provided by the SAPI that populate the
superglobals for $_GET, $_POST, $_SERVER, $_ENV, and $_COOKIE. " is
basically documenting the *original intention of these functions*.

If there is anything odd with your example, is that you can modify the
values in GET/POST/etc superglobals to begin with.

"As it is easy and straight forward to have the same behaviour by using
filter_var($_GET['a'], /* other params */) and filter_var_array($_GET,
/* other params */), we propose to deprecate filter_input() and
filter_input_array()."

No. The whole point is that these functions read the raw data, the one
that wasn't filtered by the default filter (which has been inadvisably
deprecated).

I would therefore *undeprecate* filter.default, and allow these filter
functions are they currently are, because they implement the original
design idea behind this extension.

cheers,
Derick

On Wed, Jul 2, 2025 at 10:00 PM Gina P. Banyard internals@gpb.moe wrote:

Hello internals,

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

Looking at it again I think this huge deprecation RFC is not the right approach. I’m not sure what are we trying to do here but I was just checking how many deprecation had few previous versions and

PHP-8.3 - 5 deprecations - https://wiki.php.net/rfc/deprecations_php_8_3
PHP-8.4 - 22 deprecations - https://wiki.php.net/rfc/deprecations_php_8_4

And this one is 46. I know that there were few independent RFC’s but that’s a huge increase anyway and I’m not really sure it’s a good idea to do that many in a single release.

It is also not convenient for discussion in a single thread which we can be seen already. I’m not saying there should be an RFC for each deprecation but maybe having at least RFC for each section would be better as it would allow properly consider each of those depredations. Or somehow split to some logical chunks…

Kind regards,

Jakub