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
  • Formally deprecate socket_set_timeout
  • 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
  • Deprecate non-standard cast names
  • Deprecate passing spl_autoload_call() to spl_autoload_unregister()
  • Enact follow-up phase of the “Path to Saner Increment/Decrement operatorsRFC
  • Remove the disable_classes INI setting
  • Deprecate the $http_response_header predefined variable
  • Deprecate driver specific PDO constants and methods
  • Deprecate Pdo_Pgsql::PGSQL_TRANSACTION_IDLE, Pdo_Pgsql::PGSQL_TRANSACTION_ACTIVE, Pdo_Pgsql::PGSQL_TRANSACTION_INTRANS, Pdo_Pgsql::PGSQL_TRANSACTION_INERROR and Pdo_Pgsql::PGSQL_TRANSACTION_UNKNOWN
  • Deprecate attributes applying to multiple class properties/constants
  • Deprecate backticks ` as an alias for shell_exec

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. On other SAPIs, it defaults to On in the C code but is set to Off in the default php.ini files. 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.

Formally deprecate socket_set_timeout

socket_set_timeout() is an alias of stream_set_timeout() and already marked as deprecated in the documentation (“This function was previously called as set_socket_timeout() and later socket_set_timeout() but this usage is deprecated.”). Its name is misleading since it not part of the ext/sockets extension, which uses the socket_x() prefix.

We therefore propose to add:

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

to the signature.

Formally deprecate socket_set_timeout?
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. We therefore propose to add:

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

to the signature.

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. We therefore propose to add:

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

to the signature.

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. We therefore propose to add:

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

to the signature.

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. We therefore propose to add:

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

to the signature.

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. We therefore propose to add:

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

to the signature.

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

ArrayObject allows using an instance of a class as a “backing array” rather than the more typical behaviour of using a standard PHP array.

However the way this feature was designed breaks nearly every single expectation and invariant around objects not just for users, but also the engine.

It allows accessing private and protected properties from the global scope, write multiple times to readonly properties, write values of invalid types to typed properties, misshandles isset() and empty(), allows writing dynamic properties without issuing any warning , and can even add dynamic properties to internal classes that ban dynamic properties, doesn't call the magic __get() and __set() methods, and probably some other hidden issues.

One example to showcase some of the issues is the following:

<?php
class T {
    private readonly int $p;
    public string $p2;
 
    public function getP() {
        return $this->p;
    }
}
 
$o = new T();
$a = new ArrayObject($o);
$a["\0T\0p"] = 'str';
var_dump($o->getP());
$a["\0T\0p"] = 'modified';
var_dump($o->getP());
var_dump(isset($a["p2"]));
var_dump($o->p2);

which outputs the following:

string(3) "str"
string(8) "modified"
bool(true)
 
Fatal error: Uncaught Error: Typed property T::$p2 must not be accessed before initialization in php-wasm run script:%d
Stack trace:
#0 {main}
  thrown in php-wasm run script on line %d

As such we recommend deprecating passing an object to the constructor of ArrayObject.

Deprecate ArrayObject with objects?
Real name Yes No
Final result: 0 0
This poll has been closed.

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. Since a warning is considered stronger than a deprecation, the error code should not change, but we propose that

  • The behavior trigger an error in PHP 9
  • The warning messages in 8.5+ indicate that the behavior will trigger an error in PHP 9

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”

Since a warning is considered stronger than a deprecation, the error code should not change, but we propose that

  • The behavior trigger errors in PHP 9
  • The warning messages in 8.5+ indicate that the behavior will trigger errors in PHP 9

Deprecate non-standard cast names

This supercedes the following inactive RFC Deprecate Inconsistent Cast Names.

We propose to deprecate the following non-standard cast names:

  • (integer)
  • (boolean)
  • (double)

This is inline how using non-standard names for built-in types emits a “confusable” warning at compile time, for example:

<?php
 
function foo(integer $x) {
 
}

Causes the following warning to be emitted:

Warning: “integer” will be interpreted as a class name. Did you mean “int”? Write “\integer” to suppress this warning

For consistency reasons with the rest of the language we propose to deprecate such casts and recommend using the standard ones.

Deprecate non-standard cast names?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate passing spl_autoload_call() to spl_autoload_unregister()

The spl_autoload_register() function allows registering a callable to find classes during autoloading. Naturally it prevents passing the spl_autoload_call() as a callback, as this would be non-sensical.

However, the spl_autoload_unregister() function, which is used to remove a callback from the autoloading sequence does permit passing the spl_autoload_call() function as a callback, in which case all autoloading callbacks are removed.

This behaviour is undocumented and frankly baffling, as such we propose to deprecate passing spl_autoload_call() to spl_autoload_unregister().

If there is a need to remove all autoloading functions it is possible to do so via the following obvious method:

foreach (spl_autoload_functions() as $fn) {
    spl_autoload_unregister($fn);
}
Deprecate passing spl_autoload_call() to spl_autoload_unregister()?
Real name Yes No
Final result: 0 0
This poll has been closed.

Enact follow-up phase of the "Path to Saner Increment/Decrement operators" RFC

The Path to Saner Increment/Decrement operators RFC delayed the deprecation of the PERL string increment feature so that users could have time to migrate to the new str_increment() function introduced in PHP 8.3.

As there have been two minor versions to allow this migration we now proposed to enact the following delayed deprecation from the RFC:

Deprecate using the increment operator with non-numeric strings.

Enact follow-up phase of the Path to Saner Increment/Decrement operators RFC?
Real name Yes No
Final result: 0 0
This poll has been closed.

Remove disable_classes INI setting

This supercedes the following inactive RFC Remove disable_classes INI setting.

The disable_classes INI setting is fundamentally useless and causes various issues in the engine, as using it will result in unexpected states for the engine to deal with.

Only internal classes can be disabled, which brings the following observation. On a minimal build of PHP, with only the mandatory extensions enabled, there are 148 classes/interfaces/traits defined. [2]

Other than a specific subset of classes defined in the SPL extension, disabling any of these classes will cause issues within the engine. Moreover, the subset of SPL classes that could be disabled are not a security concern.

Therefore, any other class that can be disabled must come from an extension that can be disabled altogether. And “disabling” a class from an extension without disabling said extension will, other than rendering it useless, cause various issues that the extension is not prepared to handle as they expect the classes they defined to exist.

If a hosting provider is concerned about an extension, then it should not enable it in the first place. Not break it ad hoc.

Considering the above, the usefulness of this feature has always been dubious.

This is in stark contrast to the disable_functions INI setting, which can be used to selectively remove functionality of an extension without breaking it overall.

What makes this setting particularly broken is that it does not unregister the class, it only overwrites the create CE handler to emit a warning and purge the properties and function hash tables. This leads to various use after free, segfaults, and broken expectations for the engine and extensions which define said classes. On top of that, it is possible to actually instantiate such a class (and even classes which actually disallow this like ext/imap) in userland, and pass it to functions that are typed against said class without raising a TypeError. However, when trying to do anything with said object, stuff is going to explode in countless ways.

The only usage we can find is within the Fuzzer SAPI to block instantiation of the InfiniteIterator class so that it does not try to fuzz this class. This can be fixed by manually changing the create handler of the InfiniteIterator CE to throw in the fuzzer initiation code.

As such we propose removing the disable_classes INI setting.

Remove disable_classes INI setting?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate the $http_response_header predefined variable

This was initially slated for deprecation in PHP 8.1, however it was removed from the proposal as there were no practical alternatives for this functionality.

This was addressed in PHP 8.4 by adding the http_get_last_response_headers() function. As the usage of this predefined variable is small, at the time of the RFC introducing the new functions, 65 times. And it is possible to write cross version compatible code in the following way:

$content = file_get_contents('http://example.com/');
if (function_exists('http_get_last_response_headers')) {
    $http_response_header = http_get_last_response_headers();
}
// Use $http_response_header as before

We propose deprecating using the $http_response_header without having previously called http_get_last_response_headers()

Deprecate the $http_response_header predefined variable?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate driver specific PDO constants and methods

With the acceptance and merging of the PDO driver specific sub-classes RFC, the recommended way to provide driver specific functionality is by creating a subclass of PDO with said functionality. As such we propose deprecating the overloaded PDO constants which are declared using the REGISTER_PDO_CLASS_CONST_LONG macros and the overloaded PDO methods which are defined in the pgsql_driver.stub.php and sqlite_driver.stub.php files.

This means the following PDO constants would be deprecated:

  • PDO::DBLIB_ATTR_CONNECTION_TIMEOUT
  • PDO::DBLIB_ATTR_QUERY_TIMEOUT
  • PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER
  • PDO::DBLIB_ATTR_VERSION
  • PDO::DBLIB_ATTR_TDS_VERSION
  • PDO::DBLIB_ATTR_SKIP_EMPTY_ROWSETS
  • PDO::DBLIB_ATTR_DATETIME_CONVERT
  • PDO::FB_ATTR_DATE_FORMAT
  • PDO::FB_ATTR_TIME_FORMAT
  • PDO::FB_ATTR_TIMESTAMP_FORMAT
  • PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
  • PDO::MYSQL_ATTR_LOCAL_INFILE
  • PDO::MYSQL_ATTR_INIT_COMMAND
  • PDO::MYSQL_ATTR_MAX_BUFFER_SIZE
  • PDO::MYSQL_ATTR_READ_DEFAULT_FILE
  • PDO::MYSQL_ATTR_READ_DEFAULT_GROUP
  • PDO::MYSQL_ATTR_COMPRESS
  • PDO::MYSQL_ATTR_DIRECT_QUERY
  • PDO::MYSQL_ATTR_FOUND_ROWS
  • PDO::MYSQL_ATTR_IGNORE_SPACE
  • PDO::MYSQL_ATTR_SSL_KEY
  • PDO::MYSQL_ATTR_SSL_CERT
  • PDO::MYSQL_ATTR_SSL_CA
  • PDO::MYSQL_ATTR_SSL_CAPATH
  • PDO::MYSQL_ATTR_SSL_CIPHER
  • PDO::MYSQL_ATTR_SERVER_PUBLIC_KEY
  • PDO::MYSQL_ATTR_MULTI_STATEMENTS
  • PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT
  • PDO::MYSQL_ATTR_LOCAL_INFILE_DIRECTORY
  • PDO::ODBC_ATTR_USE_CURSOR_LIBRARY
  • PDO::ODBC_ATTR_ASSUME_UTF8
  • PDO::ODBC_SQL_USE_IF_NEEDED
  • PDO::ODBC_SQL_USE_DRIVER
  • PDO::ODBC_SQL_USE_ODBC
  • PDO::PGSQL_ATTR_DISABLE_PREPARES
  • PDO::PGSQL_TRANSACTION_IDLE
  • PDO::PGSQL_TRANSACTION_ACTIVE
  • PDO::PGSQL_TRANSACTION_INTRANS
  • PDO::PGSQL_TRANSACTION_INERROR
  • PDO::PGSQL_TRANSACTION_UNKNOWN
  • PDO::SQLITE_DETERMINISTIC
  • PDO::SQLITE_ATTR_OPEN_FLAGS
  • PDO::SQLITE_OPEN_READONLY
  • PDO::SQLITE_OPEN_READWRITE
  • PDO::SQLITE_OPEN_CREATE
  • PDO::SQLITE_ATTR_READONLY_STATEMENT
  • PDO::SQLITE_ATTR_EXTENDED_RESULT_CODES

And the following overloaded PDO methods would be deprecated:

  • PDO::pgsqlCopyFromArray()
  • PDO::pgsqlCopyFromFile()
  • PDO::pgsqlCopyToArray()
  • PDO::pgsqlCopyToFile()
  • PDO::pgsqlGetNotify()
  • PDO::pgsqlGetPid()
  • PDO::pgsqlLOBCreate()
  • PDO::pgsqlLOBOpen()
  • PDO::pgsqlLOBUnlink()
  • PDO::sqliteCreateAggregate()
  • PDO::sqliteCreateCollation()
  • PDO::sqliteCreateFunction()
Deprecate driver specific PDO constants and methods?
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate attributes applying to multiple class properties/constants

Multiple class properties or constants can be declared in a single declaration, e.g.

<?php
 
#[Attribute]
class Test {}
 
class Foo {
    #[Test]
    public $bar, $baz;
 
    #[Test]
    public const BAR = 1, BAZ = 2;
}

This can be confusing, because the attributes are added to all of the properties/constants in the declaration, not just the first.

Because of the potential for confusion, when attributes were added to compile-time constants in attributes-on-constants, adding attributes to multiple non-class constants at once was not allowed.

We now propose to deprecate the same confusing behavior for the existing cases of class properties/constants.

Deprecate attributes applying to multiple class properties/constants
Real name Yes No
Final result: 0 0
This poll has been closed.

Deprecate backticks as an alias for shell_exec

Backticks are a rarely used and somewhat unknown feature of PHP that can cause confusion and hide the need for error handling by not allowing access to exit codes.

  • In code review, it's hard to spot the difference between ` and ' at a glance.
  • JavaScript uses it for template strings, causing confusion between the syntax, even for more senior developers switching between the languages.
  • It's not trivial to look up what the operator does.
  • Refactoring efforts, even for complex calls, are minimal thanks to <<<'NOWDOC'.
  • It would eventually free up the backtick operator for future use.
  • Simplifies the languages for humans, static analysis and other tooling.
  • Hides the need for escapeshellarg more than other ways of executing shell code.

Therefore, we propose to deprecate the backtick operator.

Deprecate backticks as an alias for shell_exec?
Real name Yes No
Final result: 0 0
This poll has been closed.

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/18 14:35 by edorian



Table of Contents