rfc:deprecations_php_8_5

PHP RFC: Deprecations for PHP 8.5

Introduction

The RFC proposes to deprecate the listed functionality in PHP 8.5 and remove it in PHP 9 (except where otherwise noted).

The following list provides a short overview of the functionality targeted for deprecation, while more detailed explanation is provided in the Proposal section:

  • Deprecate key_length parameter of openssl_pkey_derive()
  • Deprecate PDO's 'uri:' scheme
  • Deprecate PDO::ERRMODE_WARNING error mode
  • Deprecate intl.error_level INI setting
  • Deprecate Reflection*::setAccessible()
  • Deprecate FILTER_DEFAULT constant
  • Make $filter parameter mandatory for filter_*() functions
  • Deprecate FILTER_CALLBACK filter
  • Deprecate the docref_root and docref_ext INI directives
  • Deprecate the error_prepend_string and error_append_string INI directives
  • Deprecate the report_memleaks INI directive
  • Deprecate the register_argc_argv INI directive
  • Formally deprecate mysqli_execute
  • Deprecate __construct() and __destruct() in interfaces
  • Deprecate semicolon after case in switch statement
  • Deprecate the $exclude_disabled parameter of get_defined_functions()
  • Deprecate building ext/ldap against Oracle LDAP
  • Deprecate passing null to readdir(), rewinddir(), and closedir()
  • Deprecate the $context parameter for finfo_buffer()
  • Deprecate finfo_close()
  • Deprecate xml_parser_free()
  • Deprecate curl_close()
  • Deprecate curl_share_close()
  • Deprecate imagedestroy()
  • Deprecate DATE_RFC7231 and DateTimeInterface::RFC7231
  • Deprecate ArrayObject with objects
  • Deprecate SplObjectStorage::contains(), SplObjectStorage::attach(), and SplObjectStorage::detach()
  • Deprecate using values of type null, bool, and float as array offsets and when calling array_key_exists()
  • Deprecate __debugInfo() returning null
  • Deprecate constant redeclaration
  • Deprecate Closure binding issues

Proposal

Each feature proposed for deprecation is voted separately and requires a 2/3 majority. All votes refer to deprecation in PHP 8.5 and removal in PHP 9 (except where otherwise noted).

Deprecate key_length parameter of openssl_pkey_derive()

This parameter is useless and confusing for users. It just truncates length for ECDH but does nothing or fails for increasing lengths and DH truncation. This was raised during the security audit.

See: https://github.com/php/doc-en/pull/3789

Deprecate PDO's 'uri:' scheme

PDO supports a uri: DSN scheme that does not refer to a database driver named “uri” but instead is an indication to read the actual DSN from the specified URI, including remote stream wrappers, such as HTTP URIs.

While this feature might appear to be useful to make it easier for environment-specific configuration of an application, the username and password notably are not part of the DSN, which would require a separate configuration mechanism and which point the actual DSN could use it as well. Similarly authentication via TLS certificates with the MySQL driver would require specifying the certificate and private key as the $options.

In case of remote stream wrappers, the feature can be actively dangerous, unless the URL referenced is 100% trustworthy, since the username and password for the database might be sent to an untrusted database servers. In case of the SQLite PDO driver, a remote URL might enable access to arbitrary SQLite files on the server. Furthermore remote stream wrappers might result in performance-bottlenecks, since the file is requested for every single connection.

If this feature is somehow exactly what is desired, it can easily replicated in userland as follows (while preserving the main semantics of only looking at the first line):

$dsn = '…';
if (str_starts_with($uri, 'uri:')) {
    if (($f = fopen(substr($uri, strlen('uri:')), 'rb'))) {
        $dsn = fgets($f, 512);
        fclose($f);
    } else {
        // Emit error message
    }
}
Deprecate PDO’s uri: scheme?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate PDO::ERRMODE_WARNING error mode

PDO can be set to report errors in 3 different ways:

  • PDO::ERRMODE_SILENT
  • PDO::ERRMODE_WARNING
  • PDO::ERRMODE_EXCEPTION

In silent mode, PDO will proceed if an error has occured within a PDO statement or PDO instance, and set the error code and info so that it can be queried manually. This allows for a more hands on approach to error handling.

In exception mode, PDO will instead throw a PDOException whenever an error occurs, and unwind the stack unless it the exception is caught via a catch block. This is a more of a hands off approach as error handling doesn't need to be done after each method call of a PDO or PDO statement instance. This mode has been the default since PHP 8.0.

In warning mode, PDO will behave similarly as if set in silent mode, but also raise an E_WARNING similarly to how the exception mode behaves. As such this mode is a bit non-sensical as it is both a hands on and hands off approach to error handling. Moreover, an E_WARNING may be promoted to an exception via an error handler set via set_error_handler(), something that might not be expected by code written with PDO::ERRMODE_SILENT in mind.

As such we propose to deprecate the PDO::ERRMODE_WARNING constant and recommend users either use the silent or exception mode.

Deprecate PDO::ERRMODE_WARNING constant?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate intl.error_level INI setting

Error handling within the Intl extension is handled by two ini settings:

  • The intl.use_exceptions INI setting which determines if errors are report by throwing an IntlException
  • The intl.error_level INI setting allows to set which type of error level should used, typically one of the E_* error constants.

Moreover, it is possible to enable both exceptions and use a non-zero error level, in which case the error is emitted first. This means that it can be “caught” via an error handler set with set_error_handler() first and be promoted to an exception different than IntlException.

However, more concerningly is that the error level could be set to E_ERROR which would trigger a bailout of the PHP VM. PHP's bailout mechanism is generaly reserved for severe engine failures, such as being unable to allocate memory.

There are multiple issues with bailouts which are described in detail in the "Issues with fatal errors" section of the Exceptions in the engine (for PHP 7) RFC. Some of them are:

  • finally blocks are not executed
  • Destructors are not executed
  • Memory may not be freed

As this INI setting has some of the same pitfalls as the PDO::ERRMODE_WARNING constant and can cause bailouts, we propose deprecating this INI setting, meaning setting it to any value different than 0 will raise an E_DEPRECATED diagnostic.

Deprecate intl.error_level INI setting?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate Reflection*::setAccessible()

The “Make reflection setAccessible() no-op” RFC in PHP 8.1 made the Reflection*::setAccessible() methods a noop. However it did not deprecate the methods to simplify cross-version compatibility.

Since PHP 8.0, which is the last version where the methods did anything, is already EOL and PHP 8.1, which introduced the change will be EOL shortly after the release of PHP 8.5, it seems reasonable to deprecate the methods to make users aware that they have no effect (especially for calls to ->setAccessible(false)) and to encourage users to remove them.

If compatibility with PHP 8.0 or earlier is desired, the deprecation can be suppressed with @ or alternatively the call to ->setAccessible() can be guarded by an if (PHP_VERSION_ID < 80100) check.

We therefore propose to add:

#[\Deprecated(since: '8.5', message: "as this method does nothing")]

to the signature.

Deprecate Reflection*::setAccessible()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate FILTER_DEFAULT constant

The FILTER_DEFAULT constant is an alias for the FILTER_UNSAFE_RAW constant. This has been the case since at least PHP 5.3. This is confusing and seems to indicate that it corresponds to the filter set by the filter.default INI setting. Moreover, this INI setting was deprecated in PHP 8.1.

As this constant is confusing and misleading, we propose to deprecate it.

Deprecate FILTER_DEFAULT constant?
Real name Yes No
Final result: 0 0
This poll has been closed.

Make $filter parameter mandatory for filter_*() functions

The filter_*() functions do not require passing the $filter parameter, the default value of it is FILTER_DEFAULT which is an alias for the FILTER_UNSAFE_RAW filter. This filter does nothing if no flags are provided. This behaviour is indicative of a bug, therefore, we propose to make the $filter argument mandatory and emit a deprecation notice if the default value is used.

Emit a deprecation notice when using the default value for the $filter argument of the filter_*() functions?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate FILTER_CALLBACK filter

The FILTER_CALLBACK filter allows providing a function to call on the value to filter. This makes little sense as one can pass the value to filter directly to the function instead of passing by the filter extension.

Similarly, to filter an array of values, it is easier and more intuitive to use the array_map() function rather than the filter extension.

As such, we propose to deprecate this filter.

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

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.

This means that modification to any entry of the superglobal will not be used when calling these functions. This is showcased by the following PHPT test:

--TEST--
filter_input() filter with superglobal modified
--EXTENSIONS--
filter
--GET--
a=hello
--FILE--
<?php
 
var_dump($_GET);
$f1 = filter_input(INPUT_GET, "a", FILTER_CALLBACK, ['options' => fn (string $s) => $s === "world"]);
var_dump($f1);
 
$_GET['a'] = "world";
var_dump($_GET);
$f2 =filter_input(INPUT_GET, "a", FILTER_CALLBACK, ['options' => fn (string $s) => $s === "world"]);
var_dump($f2);
var_dump($_GET);
 
?>
--EXPECT--
array(1) {
  ["a"]=>
  string(5) "hello"
}
bool(false)
array(1) {
  ["a"]=>
  string(5) "world"
}
bool(false)
array(1) {
  ["a"]=>
  string(5) "world"
}

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().

As filter_has_var() is effectively equivalent to array_key_exists(), but has the same caveat as the two previous functions, we propose to also deprecate this function.

Deprecate the docref_root and docref_ext INI directives

Both of these INI settings allow overriding the output of HTML diagnostic errors (warning, notice, deprecations, etc.) to change the base URL and file extension for the clickable links pointing to functions and/or INI settings in error messages generated by calls to php_error_docref().

This is a debug feature and had some value when the php.net documentation had mirrors, considering those have been retired, their use is now limited.

As such, we propose deprecating those two INI settings.

Deprecate the docref_root and docref_ext INI directives?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the error_prepend_string and error_append_string INI directives

Both of these INI settings allow overriding the output of HTML diagnostic errors (warning, notice, deprecations, etc.) to prepend or append HTML before the generated HTML of these diagnostic errors.

This is a development and debugging feature which seems somewhat questionable and of limited use.

As such, we propose deprecating those two INI settings.

Deprecate the error_prepend_string and error_append_string INI directives?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the report_memleaks INI directive

This INI directive allows to suppress ZendMM memory leaks in debug builds of PHP. This “feature” is highly questionable, as memory leaks should be fixed the moment they are made aware of. Because this cannot affect production builds of PHP we propose deprecating this INI setting.

Deprecate the report_memleaks INI directive?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the register_argc_argv INI directive

This INI directive tells PHP whether to declare the argv & argc variables. On the CLI, phpdbg and embed SAPIs it is forced to On. It defaults to Off on other SAPIs. This setting is dangerous on HTTP SAPIs because it allows defining the value of the argv/argc variables from the query string. This is almost always unwanted and certainly unexpected. It can lead to security issues if one reads argv/argc from an HTTP apps while not being aware of this behavior.

We propose to deprecate this INI setting and make in default to Off in PHP 8.5, then to hardcode it to Off for all non-CLI-related SAPIs on PHP 9 (while keeping it hardcoded to On for CLI-related ones).

Formally deprecate mysqli_execute

mysqli_execute() is an alias of mysqli_stmt_execute() and already marked as deprecated in the documentation (“mysqli_execute() is deprecated and will be removed.”). Its name is misleading since it operates on an mysqli_stmt object, rather than an mysqli object, leading to possible confusion with the mysqli_execute_query() function added in PHP 8.2 that does operate on an mysqli object.

We therefore propose to add:

#[\Deprecated(since: '8.5', message: "use mysqli_stmt_execute() instead")]

to the signature.

Formally deprecate mysqli_execute?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate __construct() and __destruct() in interfaces

Deprecate semicolon after case in switch statement

It is possible to terminate case statements with a semicolon instead of the standard colon:

switch ($value) {
    case 'foo';
    case 'bar':
    case 'baz';
        echo 'foo, bar, or baz';
        break;
    default;
        echo 'Other';
}

This syntax is a leftover from PHP/FI 2, where nearly all lines including if conditions and case statements were terminated by a semicolon. 1 2

There isn't a need for this syntax to exist anymore, and very few PHP developers are even aware of its existence. In the top 1000 Composer packages, zero out of 35,777 total case statements are using the alternate syntax (as of 2024-11-27). Edit: as of 2025-06-02 there are still zero usages of the alternate syntax in the top 1000 packages (out of 29,858 total case statements).

Case statements followed by a semicolon can cause confusion, as a developer may think they behave differently in some way from regular case statements (e.g. preventing fallthrough), when they do not.

Therefore, we propose to deprecate terminating case statements with a semicolon.

Deprecate semicolon-terminated case statements?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the $exclude_disabled parameter of get_defined_functions()

As of PHP 8.0.0, functions that are disabled via the disable_functions INI setting are simply removed from the function table. As such, this parameter no longer has any effect and is pointless. Therefore, we propose to deprecate it.

Deprecate the $exclude_disabled parameter of get_defined_functions()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate building ext/ldap against Oracle LDAP

Building ext/ldap against Oracle LDAP had been supported, and is theoretically still supported, but is apparently broken for a while. The Oracle LDAP implementation is part of Oracle Instant Client, and uses an older LDAP API; apparently, there are no plans for updating this. So users are almost certainly better off to build against OpenLDAP (and if they need OCI8, to build that as shared library, and load after ext/ldap).

Therefore we supposed to deprecate building ext/ldap against Oracle LDAP.

It should be noted that the ldap_connect_wallet() function, available only as of PHP 8.3, would also be part of the deprecation, as well as other existing Oracle LDAP specific features.

Deprecate passing null to readdir(), rewinddir(), and closedir()

The readdir(), rewinddir(), and closedir() functions accept null as the value for the $dir_handle, in which case it will used the previously opened directory stream opened with opendir().

This is global state that can change if another call to opendir() is made, which could happen by calling a library function, and leading to spooky action at a distance. Prior extensions and functions that behaved this way have been deprecated, most notably the original ext/mysql extension and more recently the ext/pgsql functions that were overloaded were deprecated in PHP 8.1

As such, we propose deprecating passing null to readdir(), rewinddir(), and closedir().

Deprecate passing null to readdir(), rewinddir(), and closedir()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the $context parameter for finfo_buffer()

This parameter is unused, and the only reason it exists in the first place is because the implementation of it was delegated to a “god” C function that also was handling finfo_file() which does use the provided context.

As this parameter is not useful for this function it should be deprecated.

Deprecate the $context parameter for finfo_buffer()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate finfo_close()

Since the migration of the fileinfo extension from resources to objects in PHP 8.1, this function has been a no-op.

As the function is not needed anymore, it should be deprecated.

Deprecate xml_parser_free()

Since the migration of the xml extension from resources to objects in PHP 8.0, this function has been a no-op.

As the function is not needed anymore, it should be deprecated.

Deprecate curl_close()

Since the migration of the cURL extension from resources to objects in PHP 8.0, this function has been a no-op.

As the function is not needed anymore, it should be deprecated.

Deprecate curl_share_close()

Since the migration of the cURL extension from resources to objects in PHP 8.0, this function has been a no-op.

As the function is not needed anymore, it should be deprecated.

Deprecate imagedestroy()

Since the migration of the GD extension from resources to objects in PHP 8.0, this function has been a no-op.

As the function is not needed anymore, it should be deprecated.

Deprecate DATE_RFC7231 and DateTimeInterface::RFC7231

Because the implementation of the constant contains the timezone `GMT` designation, the format of date will always show the `GMT` timezone, despite the real timezone of the instance of `DateTimeInterface`. This may lead to unwanted results.

The implementation of this constant was a mistake, as this was described as bug. This wasn't bug, but a feature request: https://github.com/php/php-src/pull/2450

Implementation: https://github.com/php/php-src/pull/12989

Deprecate ArrayObject with objects

Documentation currently says

Wrapping objects with this class is fundamentally flawed, and therefore its usage with objects is discouraged.

TODO explain the history of ArrayObject-related bugs being closed

https://wiki.php.net/rfc/container-offset-behaviour#arrayobject

Deprecate SplObjectStorage::contains(), SplObjectStorage::attach(), and SplObjectStorage::detach()

This is lifted from the Improve language coherence for the behaviour of offsets and containers RFC as it is time sensitive.

The following three methods are aliases for methods defined by ArrayAccess, namely:

  • SplObjectStorage::contains() is an alias for SplObjectStorage::offsetExists()
  • SplObjectStorage::attach() is an alias for SplObjectStorage::offsetSet()
  • SplObjectStorage::detach() is an alias for SplObjectStorage::offsetUnset()

However, extending `SplObjectStorage` and overwriting one of the alias methods does not modify the behaviour of using the offset access operators. Meaning that it is possible to have an asymetry between using methods calls and the overloaded offset access operators.

As such we propose deprecating the method aliases in favour of using the ArrayAccess methods.

Deprecate SplObjectStorage::contains(), SplObjectStorage::attach(), and SplObjectStorage::detach()?
Real name Yes No
Final result: 0 0
This poll has been closed.

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

This is lifted from the Improve language coherence for the behaviour of offsets and containers RFC as it is time sensitive.

How offsets are handled in PHP is rather unintuitive and not consistent with many other areas of the language. Notably an offset of null is type juggled to the empty string "" rather than 0, contrasting with how values of type bool, float, and resources are cast to int. Which is even more surprising that the other operators that accept both string and int are bitwise operators and they throw a type error when attempting to use null with a value of type string.

Moreover, invalid types for string offsets always warn, which is not the case for array offsets (except when using a resource).

As such we propose deprecating using values of type null, bool, and float as array offsets and when calling array_key_exists()

Deprecate using values of type null, bool, and float as array offsets and when calling array_key_exists()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate __debugInfo() returning null

Since the __debugInfo() magic method was added, it has been documented as needing to return an array (see original implementation) in the error message if you return a non-array and non-null value.

However, null has been silently treated the same as an empty array.

This can result in confusion about if null means something different. Accordingly, we propose to deprecate returning null from __debugInfo() magic methods.

Deprecate constant redeclaration

In PHP 8, attempting to declare a constant that already existing was changed to emit a warning rather than just a notice. We propose to elevate this in PHP 8.5 to a deprecation (and in 9.0 to an error).

Redeclaring a constant can lead to invalid assumptions, specifically if a developer assumes that the declaration will succeed they may assume a constant has one value when it actually has a different value.

Deprecate closure binding issues

When trying to bind a Closure object, multiple issues can potentially be raised, but only as warnings:

  • “Cannot bind an instance to a static closure”
  • “Cannot bind method %s::%s() to object of class %s” - for trying to change the type of object bound to
  • “Cannot unbind $this of method”
  • “Cannot unbind $this of closure using $this”
  • “Cannot bind closure to scope of internal class %s”
  • “Cannot rebind scope of closure created from function”
  • “Cannot rebind scope of closure created from method”

We propose to elevate these in PHP 8.5 to deprecations (and in 9.0 to errors).

Backward Incompatible Changes

For PHP 8.5 additional deprecation notices will be emitted. The actual removal of the affected functionality will happen no earlier than PHP 9.

Removed from this proposal

The following entries were originally added to this proposal and then dropped.

rfc/deprecations_php_8_5.txt · Last modified: 2025/06/02 16:42 by theodorejb



Table of Contents