PHP RFC: Deprecations for PHP 8.5
- Date: 2024-09-26
- Authors:
- Gina Peter Banyard girgias@php.net
- Christoph M. Becker cmb@php.net
- Daniel Scherzer daniel.e.scherzer@gmail.com
- Theodore Brown theodorejb@php.net
- Jorg Sowa jorg.sowa@gmail.com
- Status: Draft
- Implementation: TBD
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 ofopenssl_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 forfilter_*()
functions - Deprecate FILTER_CALLBACK filter
- Deprecate the
docref_root
anddocref_ext
INI directives - Deprecate the
error_prepend_string
anderror_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 ofget_defined_functions()
- Deprecate building ext/ldap against Oracle LDAP
- Deprecate the
$context
parameter forfinfo_buffer()
- Deprecate
finfo_close()
- Deprecate
xml_parser_free()
- Deprecate
curl_close()
- Deprecate
curl_share_close()
- Deprecate
imagedestroy()
- Deprecate
DATE_RFC7231
andDateTimeInterface::RFC7231
- Deprecate
ArrayObject
with objects - Deprecate
SplObjectStorage::contains()
,SplObjectStorage::attach()
, andSplObjectStorage::detach()
- Deprecate using values of type
null
,bool
, andfloat
as array offsets and when callingarray_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.
Deprecate PDO's 'uri:' scheme
- Author: Tim Düsterhus timwolla@php.net
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):
Deprecate PDO::ERRMODE_WARNING error mode
- Author: Gina Peter Banyard girgias@php.net
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 intl.error_level INI setting
- Author: Gina Peter Banyard girgias@php.net
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 anIntlException
- The
intl.error_level
INI setting allows to set which type of error level should used, typically one of theE_*
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 Reflection*::setAccessible()
- Author: Tim Düsterhus timwolla@php.net
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 FILTER_DEFAULT constant
- Author: Gina Peter Banyard girgias@php.net
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.
Make $filter parameter mandatory for filter_*() functions
- Author: Gina Peter Banyard girgias@php.net
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.
Deprecate FILTER_CALLBACK filter
- Author: Gina Peter Banyard girgias@php.net
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()
- Author: Gina Peter Banyard girgias@php.net
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
- Author: Gina Peter Banyard girgias@php.net
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 error_prepend_string and error_append_string INI directives
- Author: Gina Peter Banyard girgias@php.net
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 report_memleaks INI directive
- Author: Gina Peter Banyard girgias@php.net
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 register_argc_argv INI directive
- Author: Nicolas Grekas nicolas.grekas@php.net
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
- Author: Tim Düsterhus timwolla@php.net
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.
Deprecate __construct() and __destruct() in interfaces
- Author: Tim Düsterhus timwolla@php.net
TODO: https://phpc.social/@dseguy/113476785631597024 / https://github.com/php/php-src/issues/16077
Deprecate semicolon after case in switch statement
- Author: Theodore Brown theodorejb@php.net
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 the $exclude_disabled parameter of get_defined_functions()
- Author: Gina Peter Banyard girgias@php.net
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 building ext/ldap against Oracle LDAP
- Author: Christoph M. Becker cmb@php.net
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()
- Author: Gina Peter Banyard girgias@php.net
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 the $context parameter for finfo_buffer()
- Author: Gina Peter Banyard girgias@php.net
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 finfo_close()
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
- Implementation: https://github.com/php/php-src/pull/18396
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()
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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()
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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()
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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()
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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
- Author: Jorg Sowa jorg.sowa@gmail.com
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
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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()
- Author: Gina Peter Banyard girgias@php.net
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 forSplObjectStorage::offsetExists()
SplObjectStorage::attach()
is an alias forSplObjectStorage::offsetSet()
SplObjectStorage::detach()
is an alias forSplObjectStorage::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 using values of type null, bool, and float as array offsets and when calling array_key_exists()
- Author: Gina Peter Banyard girgias@php.net
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 __debugInfo() returning null
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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
- Author: Daniel Scherzer daniel.e.scherzer@gmail.com
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.