# RFC: Deprecations for PHP 8.4

- Status: Accepted
- Authors: Niels Dossche nielsdos@php.net Gina Peter Banyard girgias@php.net Máté Kocsis kocsismate@php.net Tim Düsterhus timwolla@php.net Kamil Tekiela dharman@php.net Jorg Sowa jorg.sowa@gmail.com
- Date: 2023-07-25
- Implementation: pending (for user output handlers returning non-strings), 8.5 (for user output handlers producing output), 8.4 (everything else) Formally deprecate Soft-deprecated DOMDocument and DOMEntity properties Remove DOMImplementation::getFeature($feature, $versio
- Original: https://wiki.php.net/rfc/deprecations_php_8_4
- Page: https://externals.io/rfc/deprecations_php_8_4
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Formally deprecate and remove the aforementioned DOMDocument and DOMEntity properties? (closed)

Yes: 36 · No: 0

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Remove DOMImplementation::getFeature($feature, $version) (closed)

Yes: 38 · No: 0

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jhdxr (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate DOM_PHP_ERR constant? (closed)

Yes: 37 · No: 0

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jhdxr (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate unserialize()’s ‘S’ tag? (closed)

Yes: 36 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), levim (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate the INI settings ‘session.sid_length’ and ‘session.sid_bits_per_character’? (closed)

Yes: 35 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), levim (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate SplFixedArray::__wakeup()? (closed)

Yes: 36 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), levim (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate xml_set_object() and xml_set_*_handler() with string method names (closed)

Yes: 33 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate passing null and false to dba_key_split() (closed)

Yes: 33 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), devnexen (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate passing incorrect data types for options to ext/hash functions (closed)

Yes: 33 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (Yes), devnexen (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), levim (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate constants SUNFUNCS_RET_STRING, SUNFUNCS_RET_DOUBLE, and SUNFUNCS_RET_TIMESTAMP? (closed)

Yes: 32 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate passing a non-empty string to the $escape parameter (closed)

Yes: 26 · No: 2

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), jhdxr (No), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Remove the E_STRICT Error Level and Deprecate the E_STRICT constant? (closed)

Yes: 29 · No: 5

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), brzuchal (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (No), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jhdxr (No), jimw (Yes), kalle (Yes), kguest (Yes), levim (No), mauricio (Yes), mbeccati (No), nicolasgrekas (Yes), nielsdos (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), saki (Yes), sebastian (No), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate strtok()? (closed)

Yes: 6 · No: 27

Voters: alcaeus (Yes), asgrim (No), beberlei (No), brzuchal (Yes), bukka (No), bwoebi (No), crell (No), cschneid (No), derick (No), dharman (No), ericmann (No), galvao (No), girgias (Yes), heiglandreas (No), jhdxr (No), jimw (No), kalle (No), kguest (No), kocsismate (Yes), mauricio (No), mbeccati (No), nicolasgrekas (Yes), nielsdos (No), nikic (No), ocramius (No), patrickallaert (No), petk (Yes), pierrick (No), saki (No), sergey (No), svpernova09 (No), thorstenr (No), weierophinney (No)

### Deprecate returning non-string values from a user output buffer handler? (closed)

Yes: 23 · No: 4

Voters: alcaeus (Yes), asgrim (Yes), bukka (No), bwoebi (Yes), cmb (No), crell (Yes), cschneid (Yes), derick (No), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (No), nicolasgrekas (Yes), ocramius (Yes), petk (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate producing output in a user output handler? (closed)

Yes: 25 · No: 2

Voters: alcaeus (Yes), asgrim (Yes), bukka (No), bwoebi (Yes), cmb (No), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), levim (Yes), mauricio (Yes), ocramius (Yes), petk (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate using an array as the $data argument for file_put_contents() (closed)

Yes: 20 · No: 15

Voters: alcaeus (Yes), asgrim (Yes), beberlei (No), brzuchal (Yes), bukka (No), bwoebi (No), crell (Yes), cschneid (No), derick (No), dharman (No), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (No), jimw (No), josh (Yes), kalle (Yes), kguest (No), lufei (Yes), mauricio (Yes), mbeccati (No), nicolasgrekas (No), nielsdos (No), ocramius (Yes), patrickallaert (No), petk (Yes), pierrick (No), reywob (Yes), sergey (Yes), shivam (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (No), timwolla (Yes), weierophinney (Yes)

### Deprecate mysqli_ping() and mysqli::ping()? (closed)

Yes: 27 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nikic (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate mysqli_refresh(), mysqli::refresh() and related constants? (closed)

Yes: 27 · No: 1

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate mysqli_kill() and mysqli::kill()? (closed)

Yes: 27 · No: 1

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate the second parameter to mysqli_store_result()? (closed)

Yes: 31 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), cmb (Yes), crell (Yes), cschneid (Yes), derick (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), saki (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (Yes)

### Deprecate lcg_value()? (closed)

Yes: 29 · No: 2

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (No), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), nikic (Yes), ocramius (Yes), petk (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate uniqid()? (closed)

Yes: 14 · No: 23

Voters: alcaeus (No), alec (No), asgrim (No), beberlei (No), brzuchal (Yes), bukka (No), bwoebi (No), crell (Yes), cschneid (Yes), derick (No), dharman (Yes), dmitry (No), ericmann (No), galvao (No), girgias (Yes), heiglandreas (No), jimw (Yes), josh (Yes), kalle (No), kguest (Yes), lufei (No), mauricio (Yes), mbeccati (No), nielsdos (Yes), nikic (No), ocramius (No), patrickallaert (No), petk (Yes), pierrick (No), reywob (No), sergey (Yes), shivam (No), svpernova09 (No), theodorejb (Yes), thorstenr (No), timwolla (Yes), weierophinney (No)

### Deprecate md5(), sha1(), md5_file(), and sha1_file()? (closed)

Yes: 18 · No: 21

Voters: alcaeus (Yes), alec (No), asgrim (No), beberlei (No), brzuchal (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (No), derick (No), dharman (Yes), dmitry (No), ericmann (Yes), galvao (No), girgias (Yes), heiglandreas (No), imsop (No), jimw (No), josh (No), kalle (Yes), kguest (Yes), lufei (No), mauricio (Yes), mbeccati (No), nicolasgrekas (No), nikic (No), ocramius (Yes), patrickallaert (No), petk (Yes), pierrick (No), reywob (Yes), seld (Yes), sergey (Yes), shivam (No), svpernova09 (Yes), theodorejb (Yes), thorstenr (No), timwolla (Yes), weierophinney (No)

### Deprecate passing E_USER_ERROR to trigger_error() (closed)

Yes: 27 · No: 2

Voters: alcaeus (Yes), asgrim (Yes), beberlei (Yes), bukka (No), bwoebi (No), crell (Yes), cschneid (Yes), dharman (Yes), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nikic (Yes), ocramius (Yes), petk (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

### Deprecate using a single underscore as a class name? (closed)

Yes: 28 · No: 7

Voters: alcaeus (Yes), asgrim (Yes), brzuchal (Yes), bukka (No), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (No), dharman (Yes), dmitry (No), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), josh (Yes), kalle (No), kguest (Yes), levim (Yes), lufei (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (No), nikic (Yes), ocramius (Yes), patrickallaert (No), petk (Yes), reywob (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), weierophinney (No)

### Deprecate SOAP_FUNCTIONS_ALL constant and passing it to SoapServer::addFunction()? (closed)

Yes: 28 · No: 1

Voters: alcaeus (Yes), alec (Yes), asgrim (Yes), beberlei (Yes), bwoebi (Yes), crell (Yes), cschneid (Yes), derick (No), ericmann (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), jimw (Yes), kalle (Yes), kguest (Yes), kocsismate (Yes), mauricio (Yes), mbeccati (Yes), nicolasgrekas (Yes), nielsdos (Yes), ocramius (Yes), petk (Yes), sebastian (Yes), sergey (Yes), svpernova09 (Yes), theodorejb (Yes), thorstenr (Yes), timwolla (Yes), weierophinney (Yes)

## Discussions on the mailing list

- [Peculiar behaviour of ext/xml set_X_handler() functions](https://externals.io/message/121270.md) — started on 2023-10-10, 2 messages
- [\[RFC\] Deprecations for PHP 8.4](https://externals.io/message/123816.md) — started on 2024-06-25, 68 messages
- [\[RFC\] \[VOTE\] Deprecations for PHP 8.4](https://externals.io/message/124506.md) — started on 2024-07-19, 97 messages
- [Clarification about deprecate proprietary CSV escaping mechanism](https://externals.io/message/125628.md) — started on 2024-09-19, 2 messages
- [No more RFC implementations during beta phase](https://externals.io/message/125666.md) — started on 2024-09-24, 9 messages
- [RFCs that are pending implementation](https://externals.io/message/127985.md) — started on 2025-07-10, 2 messages

---

## Introduction

The RFC proposes to deprecate the listed functionality in PHP 8.4 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:

- Formally deprecate Soft-deprecated `DOMDocument` and `DOMEntity` properties
- Remove `DOMImplementation::getFeature($feature, $version)`
- Deprecate `DOM_PHP_ERR` Constant
- `unserialize()`'s 'S' tag
- `session.sid_length` and `session.sid_bits_per_character`
- Deprecate `SplFixedArray::__wakeup()`
- `xml_set_object()` and `xml_set_*_handler()` with string method names
- Passing `null` and `false` to `dba_key_split()`
- Deprecate passing incorrect data types for options to ext/hash functions
- Constants `SUNFUNCS_RET_STRING`, `SUNFUNCS_RET_DOUBLE`, `SUNFUNCS_RET_TIMESTAMP`
- Deprecate proprietary CSV escaping mechanism
- Deprecate `E_STRICT` Constant
- Deprecate `strtok()`
- Deprecate returning non-string values from a user output handler
- Deprecate producing output in a user output handler
- `file_put_contents()` with `$data` as an array
- Deprecate `mysqli_ping()` and `mysqli::ping()`
- Deprecate `mysqli_refresh()`
- Deprecate `mysqli_kill()`
- Deprecate the second parameter to `mysqli_store_result()`
- Deprecate `lcg_value()`
- Deprecate `uniqid()`
- Deprecate `md5()`, `sha1()`, `md5_file()`, and `sha1_file()`
- Deprecate passing `E_USER_ERROR` to `trigger_error()`
- Deprecate using a single underscore `_` as a class name
- Deprecate `SOAP_FUNCTIONS_ALL` constant and passing it to `SoapServer::addFunction()`

## Proposal

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

### Formally deprecate Soft-deprecated DOMDocument and DOMEntity properties

- Author: Máté Kocsis <kocsismate@php.net>
- Implementation: <https://github.com/php/php-src/pull/15369>

The following properties have been soft-deprecated for at least [17 years](https://github.com/php/doc-en/commit/7fde5c7d758f8c2809fec99ce36b05043847224a):

- `DOMDocument::$actualEncoding`: it is just an alias to `DOMDocument::$encoding`
- `DOMDocument::$config`: it has always returned null
- `DOMEntity::$actualEncoding`: it has always returned null
- `DOMEntity::$encoding`: it has always returned null
- `DOMEntity::$version`: it has always returned null

As such we propose to formally deprecate them.

**Vote: Formally deprecate and remove the aforementioned DOMDocument and DOMEntity properties?** — Yes: 36 · No: 0 (closed)

### Remove DOMImplementation::getFeature($feature, $version)

- Author: Niels Dossche <nielsdos@php.net>
- Implementation: <https://github.com/php/php-src/commit/d9eb3783bdd6947a635f132f8c240de8f40e8704>

`DOMImplementation::getFeature($feature, $version)` used to be a feature of DOM Core Level 3 <https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-DOMImplementation3-getFeature>, but it was never implemented in PHP, i.e. it always threw a “not implemented” exception. It was also never documented because of this. Furthermore, the feature has been removed from the current living DOM spec. It doesn't make sense to keep a feature alive that has never been implemented and is removed by the reference specification.

As such, we propose to directly remove the function as a deprecation wouldn't make much sense here.

**Vote: Remove DOMImplementation::getFeature($feature, $version)** — Yes: 38 · No: 0 (closed)

### Deprecate DOM\_PHP\_ERR Constant

- Author: Niels Dossche <nielsdos@php.net>
- Implementation: <https://github.com/php/php-src/commit/0aec0faa275df28597cd0cc82e64f7072b8e2c0f>

PR <https://github.com/php/php-src/pull/11927> got rid of the last use of `DOM_PHP_ERR` in PHP. It is a non-standard and non-well-defined error code. The last use was for an out-of-memory situation but that's inconsistent as we normally use `INVALID_STATE_ERR` for that.

GitHub search reveals [174 matches](https://github.com/search?q=DOM_PHP_ERR+language%3APHP&type=code&l=PHP) (as of Jan 20 2024) for `DOM_PHP_ERR`. There are occurrences in string-form, i.e. `"DOM_PHP_ERR"` that normally doesn't get affected, some in code quality/compatibility tools, and some in php-src fork's stub files.

The remaining actual use is in Symfony's DOMCaster in an array that maps a constant back to its actual name. They can fix the deprecation by replacing the constant with its value until versions older than PHP 8.4 no longer need to be supported by the library. There don't seem to be any other actual users of this.

**Vote: Deprecate DOM\_PHP\_ERR constant?** — Yes: 37 · No: 0 (closed)

### unserialize()'s 'S' tag

- Author: Tim Düsterhus <timwolla@php.net>
- Implementation: <https://github.com/php/php-src/pull/12309>

Strings serialized with PHP's native serialization mechanism are represented with the (lowercase) `s` tag, followed by the length of the string and the raw binary representation of the string contents. During the development of the never-released PHP 6, the serialization format of binary strings [was changed](https://github.com/php/php-src/commit/1f2d5e3b00d19bd6d0db40d7fc2badaa2d65082e) to use an escaped representation for non-ASCII characters, likely to make the serialization output compatible with PHP 6's Unicode strings where not all byte sequences are valid. This escaped format was then represented with the uppercase `S` tag [in a follow-up commit](https://github.com/php/php-src/commit/7ccba6624df074051f24efabd5d88d9c0d2a8ec0) and support for that uppercase `S` tag [added to PHP 5](https://github.com/php/php-src/commit/8f5310afad0eeef6f2e45a03f6ff7d4a2a7653ce) in an attempt to provide interoperability with serialized binary strings between PHP 5 and PHP 6. This support for the uppercase `S` tag remains in PHP until today.

PHP's native serializer is a security-sensitive part of the standard library, the simpler the logic the smaller the chance for security issues and the easier it is to verify the code for correctness. There are no tests verifying the functionality of the uppercase `S` tag and no released version emitted the uppercase `S` tag, thus deprecating and ultimately removing the support for the `S` tag is exceedingly unlikely to affect anyone.

**Vote: Deprecate unserialize()’s ‘S’ tag?** — Yes: 36 · No: 0 (closed)

### session.sid\_length and session.sid\_bits\_per\_character

- Author: Tim Düsterhus <timwolla@php.net>
- Implementation: <https://github.com/php/php-src/pull/15213>

PHP’s session extension currently contains two INI settings that allow the administrator to respectively control the length and the possible characters within emitted session IDs.

- The length may be configured as any value between 22 and 256.
- The bits per character may be selected to be either 4 (`[0-9a-f]`), 5 (`[0-9a-v]`), or 6 (`[0-9a-zA-Z,-]`), returning the characters indicated by the regular expression character group within the parentheses.

In [issue #12418](https://github.com/php/php-src/issues/12418) it was reported that configuring 6 bits per character might generate session IDs that are rejected by WAF applications, such as mod\_security. The 6 bits per character configuration might generate session IDs containing dashes, more specifically two consecutive dashes. Within an SQL query two consecutive dashes indicate the start of a comment, which is a common technique when exploiting SQL injection vulnerabilities, leading to a false positive within the WAF and rejecting any requests containing such a session ID.

The default is a 32 character SID, with 4 bits of entropy per character, resulting in a 128-bit session ID. 128 bits of entropy [is generally considered the correct choice for a secret value](https://security.stackexchange.com/a/102163/21705). More is unnecessary and less raises eyebrows. Guessing a 128 Bit value with a probability of 10^-11 would require roughly 2^46 guesses. At 100\_000 guesses per second it would take 23 years to even reach this negligible probability.

In other words changing the default values will either generate session IDs that raise eyebrows (4 bits per character with less than 32 characters or 5 bpc for less than 26 characters) or generate session IDs that are needlessly strong, increasing CPU costs, due to the additional randomness required, and increasing the chance for interoperability problems, such as the mod\_security example.

For this reason we propose to deprecate the two INI settings in favor of the opinionated choice of the current defaults of a 32 character hexadecimal session ID.

The hexadecimal character set is not expected to cause any interoperability issues, as it is the most limited one of the currently available ones and hexadecimal identifiers are likely the most commonly used. While this would increase the length of the session ID from the previous minimum of 22 characters (which is a secure choice when combined with 6 bits per character) to 32, we do not expect this to be an issue in practice. The difference in traffic is minimal and a hexadecimal session ID is trivially packed into a 16 Byte binary string using `hex2bin()`, should storage requirements of the session backend be a concern.

**Vote: Deprecate the INI settings ‘session.sid\_length’ and ‘session.sid\_bits\_per\_character’?** — Yes: 35 · No: 0 (closed)

### Deprecate SplFixedArray::\_\_wakeup()

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/9704>

`SplFixedArray` never implemented the `__sleep()` magic methods and since PHP 8.2 it implements the `__serialize()` and `__unserialize()` magic methods, meaning userland classes extending `SplFixedArray` must override those new methods.

As such the `SplFixedArray::__wakeup()` is pointless and should be deprecated.

**Vote: Deprecate SplFixedArray::\_\_wakeup()?** — Yes: 36 · No: 0 (closed)

### xml\_set\_object() and xml\_set\_\*\_handler() with string method names

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15293>

The XML extension allows registering callbacks that are invoked when encountering certain XML triggers, such as the start of a new element or a processing instruction, via the relevant `xml_set_*_handler()` function.

However, these functions also allow setting a method name, as a string, that should be called on the object provided via `xml_set_object()`. This behaviour is very strange and seems to date prior to the introduction of proper callables for object methods via the `[$objInstance, 'methodName']` syntax.

The proposal is to deprecate the `xml_set_object()` function and passing non-callable strings to the `xml_set_*_handler()` functions. This would also mean to unset a handler the value of `null` must be used instead of an empty string which is also currently allowed.

**Vote: Deprecate xml\_set\_object() and xml\_set\_\*\_handler() with string method names** — Yes: 33 · No: 0 (closed)

### Deprecate passing null and false to dba\_key\_split()

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15297>

The signature of `dba_key_split()` is currently `function dba_key_split(string|false|null $key): array|false {}`.

However, passing `null` or `false` to this function will make it immediately return `false`, this is the case since at least PHP 5.3, probably earlier.

Moreover, since PHP 8.0, this is the only way for this function to return `false`.

The proposal is to deprecate passing `null` and `false` to the `$key` parameter, which will allow to clean up the return type of this function in the next major version to just `array`.

**Vote: Deprecate passing null and false to dba\_key\_split()** — Yes: 33 · No: 0 (closed)

### Deprecate passing incorrect data types for options to ext/hash functions

- Author: Niels Dossche <nielsdos@php.net>
- Implementation: <https://github.com/php/php-src/commit/74eff98c84b26a8088fb56b5be748a3e0e1da419>

Some hash functions in ext/hash allow passing additional options via an array. The murmur and xxhash family support taking an integer “seed”, and xxh3 furthermore allows a string “secret”.

There's a problem with the implementation however in the sense that if you pass a “seed” of a type other than an integer or a “secret” of a type other than string, then these options are silently ignored. This was first reported on our bugtracker: <https://github.com/php/php-src/issues/10305>. This causes bugs because programmers are led to believe that their options are being applied but in reality they're not. The proposal is to deprecate passing incorrect types for these options, and make this scenario throw a ValueError in the next major version of PHP.

To assess the impact I performed two tests: one for xxh3 and one for murmur. For xxh3, I performed a simple `grep -rn --include \*.php xxh3` search in the sources for the top 2K packagist packages. None of them used xxh3 with the options array and so none of them can be affected by this deprecation. For murmur, I performed a simple `grep -rn --include \*.php murmur` search in the sources for the top 2K packagist packages. I found no uses of the hash function with this algorithm. Although this gives an indication, I expect most usages to be not in libraries but in end users code.

**Vote: Deprecate passing incorrect data types for options to ext/hash functions** — Yes: 33 · No: 0 (closed)

### Constants SUNFUNCS\_RET\_STRING, SUNFUNCS\_RET\_DOUBLE, SUNFUNCS\_RET\_TIMESTAMP

- Author: Jorg Sowa <jorg.sowa@gmail.com>
- Implementation: <https://github.com/php/php-src/pull/12978>

The functions `date_sunrise()`/`date_sunset()` are [already deprecated since PHP 8.1](https://externals.io/rfc/deprecations_php_8_1) and will be removed in the next major version.

The proposal is to deprecate constants `SUNFUNCS_RET_STRING`, `SUNFUNCS_RET_DOUBLE`, and `SUNFUNCS_RET_TIMESTAMP` which are used exclusively with those functions.

**Vote: Deprecate constants SUNFUNCS\_RET\_STRING, SUNFUNCS\_RET\_DOUBLE, and SUNFUNCS\_RET\_TIMESTAMP?** — Yes: 32 · No: 0 (closed)

### Deprecate proprietary CSV escaping mechanism

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15362>

This proposes to enact step 2 of the [Kill proprietary CSV escaping mechanism](https://externals.io/rfc/kill-csv-escaping) RFC. Which is to deprecate passing a non-empty string to the `$escape` parameter to all the CSV related functions, effectively disabling our problematic escaping mechanism.

This issue has once again appeared to cause issues for users as a new [GitHub issue](https://github.com/php/doc-en/issues/3086) was raised recently about this topic.

The affected functions are:

- `fputcsv()`
- `fgetcsv()`
- `str_getcsv()`

and the following `SplFileObject` methods:

- `SplFileObject::setCsvControl()`
- `SplFileObject::getCsvControl()`
- `SplFileObject::fputcsv()`
- `SplFileObject::fgetcsv()`

**Vote: Deprecate passing a non-empty string to the $escape parameter** — Yes: 26 · No: 2 (closed)

### Remove E\_STRICT error level and deprecate E\_STRICT constant

- Authors: Jorg Sowa <jorg.sowa@gmail.com>, Michael Voříšek (mvorisek)
- Implementation: <https://github.com/php/php-src/pull/13053>

The `E_STRICT` error level was primarily used in PHP 5 to point out bad coding practices. Most of those errors where [reclassified in PHP 7.0](https://externals.io/rfc/reclassify_e_strict), however it was still in use in-between PHP 7.0 and 7.4 for the [mysqli extension](https://github.com/php/php-src/pull/4406) and [htmlentities() function](https://github.com/php/php-src/pull/4407), most references to `E_STRICT` within engine tests were [removed in a PR in 2019](https://github.com/php/php-src/pull/4401).

Because this error level has no meaning anymore, we propose to remove the `E_STRICT` error level and deprecate the `E_STRICT` constant.

It should be noted that in theory external extensions could still emit a `E_STRICT` level error, but this seems unlikely.

**Vote: Remove the E\_STRICT Error Level and Deprecate the E\_STRICT constant?** — Yes: 29 · No: 5 (closed)

### Deprecate strtok() function

- Author: Michael Voříšek (mvorisek)

The `strtok()` is a wrapper around the C function of the same name and is used to split a string into tokens.

The design of this function is rather problematic and incompatible with named arguments. The first call to the function requires the string to tokenize and the initial delimiter, while follow-up calls must only provide the next delimiter. As such this function is stateful and stores the string to tokenize and how far along the string it has already tokenized.

This means it is possible to affect the state of this function from different scopes, which is very surprising, unintuitive, and potentially hard to debug (e.g. if the function is called from different fibers, or [from within a function](https://3v4l.org/eplIO)).

In general there are more appropriate alternatives such as `strpos()`, `explode()`, `preg_split()`, or writing a proper parser for more complicated situations.

Therefore, we propose to deprecate the `strtok()` function.

**Vote: Deprecate strtok()?** — Yes: 6 · No: 27 (closed)

### Deprecate returning non-string values from a user output handler

- Author: Gina Peter Banyard <girgias@php.net>

PHP's output buffering mechanism has some quirks due to its age. One of them is how the return value of a userland callback is treated. The documentation has indicated for a long time that the callback should return a string, however for most values it will try to cast the return value to a string. This is an issue because if the return value is an array it will be converted to the string `Array` but the warning will be suppressed as the output of the warning has nowhere to go.

Moreover, it treats the values `true` and `false` as special. A return value of `true` is treated like a context reset, which is identical to returning an empty string. A return value of `false` is treated like a failure to process the buffer, which will cause the handler to be disabled and pass the input buffer to the next output handler in the stack.

As the behaviour of returning values other than `string` from an output buffer is unintuitive we propose deprecating this behaviour.

Return values of `true` should be changed to an empty string, and if `false` is returned, we think it would be better to throw an exception instead.

For more information see the documentation: <https://www.php.net/manual/en/outcontrol.user-level-output-buffers.php>

**Vote: Deprecate returning non-string values from a user output buffer handler?** — Yes: 23 · No: 4 (closed)

### Deprecate producing output in a user output handler

- Author: Gina Peter Banyard <girgias@php.net>

Because an output handler should just be manipulating the incoming buffer, any output that it produces is discarded. As such, issues within an output handler can go unnoticed and be hard to debug.

Therefore, we propose deprecating producing any output in an output handler, in the same way as attempting to use an output buffering function in an output handler will emit a Fatal Error.

**Vote: Deprecate producing output in a user output handler?** — Yes: 25 · No: 2 (closed)

### file\_put\_contents() with $data as an array

- Author: Gina Peter Banyard <girgias@php.net>

Passing an array as the `$data` parameter is a surprising and unknown feature of the `file_put_contents()` function. However, if the array is not fully comprised of strings a partial write can occur as an exception might occur during the conversion of the value to string, or simply because another file acquired a lock on it.

One potential solution to this problem is to first loop through the values to check that they are strings, however this means looping twice over the values, once to check, a second time to write entry by entry.

Another potential annoyance is that the `array` type cannot be widened to `iterable` as there is no reliable way to determine how an object implementing `Stringable` and `Traversable` should be interpreted.

An analysis using Exakat on private and public codebases reveals that this feature is barely used only by a few libraries, which seem to boil down to the following:

- `symfony/error-handler/DebugClassLoader.php`
- `symfony/http-kernel/Profiler/FileProfilerStorage.php`
- `laminas/laminas-validator/bin/update_hostname_validator.php`
- `scssphp/scssphp/src/Cache.php`

As such, we propose to deprecate using an `array` for the `$data` argument of `file_put_contents()`

The simplest replacement is: `file_put_contents($filename, implode('', $data))`, however one can also open the file and use a `foreach` loop to append every individual item.

**Vote: Deprecate using an array as the $data argument for file\_put\_contents()** — Yes: 20 · No: 15 (closed)

### mysqli\_ping() and mysqli::ping()

- Authors: Gina Peter Banyard <girgias@php.net>, Kamil Tekiela <dharman@php.net>
- Implementation: <https://github.com/php/php-src/pull/11945>

The purpose of `mysqli_ping()` and `$mysqli->ping()` is to check whether the connection is live and attempt reconnection if it is not. This only works if mysqli is compiled with libmysql. The support for this has been removed in PHP 8.2. As it's no longer possible to use automatic reconnection in PHP 8.2, the `mysqli_ping()` function has become useless.

For users who simply want to check if the connection is alive, they can use `DO 1` or similar SQL query to see if it succeeds. There is no need to offer such functionality in PHP anymore.

See reasoning: <https://github.com/php/php-src/pull/11912#issuecomment-1671762583>

**Vote: Deprecate mysqli\_ping() and mysqli::ping()?** — Yes: 27 · No: 0 (closed)

### Deprecate mysqli\_refresh()

- Author: Kamil Tekiela <dharman@php.net>
- Implementation and more explanations can be found at: <https://github.com/php/php-src/pull/11929>

The `mysqli_refresh()` function and its OO counterpart `$mysqli->refresh()` are just a wrapper for the `COM_REFRESH` command. The `COM_REFRESH` command has been deprecated as of MySQL 5.7. The `mysqli_refresh()` function has very easy alternatives as it's just a binary protocol version of the SQL `FLUSH` command. On top of this, the FLUSH command accepts more parameters than the COM\_REFRESH command, which makes `mysqli_refresh()` the worse option of the two.

The proposal is to deprecate the `mysqli_refresh()` function and its OO counterpart, and promote usage of SQL queries, e.g. `FLUSH LOGS, FLUSH TABLES, FLUSH HOSTS` etc.

All of the MYSQLI\_REFRESH\_\* constants will be removed too.

**Vote: Deprecate mysqli\_refresh(), mysqli::refresh() and related constants?** — Yes: 27 · No: 1 (closed)

### Deprecate mysqli\_kill()

- Author: Kamil Tekiela <dharman@php.net>
- Implementation: <https://github.com/php/php-src/pull/11926>

The `mysqli_kill()` function and its OO counterpart `$mysqli->kill()` are just a wrapper for the `COM_PROCESS_KILL` command. The `COM_PROCESS_KILL` command has been deprecated as of MySQL 5.7. The usage of this command is to kill a running MySQL process. It's the same as executing `KILL processlist_id` SQL statement.

The only issue with deprecating this function in PHP is the way in which it has been used in PHP unit tests. The `mysqli_kill()` function has been used in PHP unit tests to kill the same MySQL process that has executed the command, effectively killing itself. Using the `KILL` SQL command would have resulted in PHP throwing an error about interrupted connection, while using the `mysqli_kill()` function does not. Suicidal use of this function was unlikely to be an intended use case. There's no reason to support such behaviour from mysqli. Users who truly need this behaviour can emulate it in userland using the `KILL` statement.

The proposal is to deprecate the `mysqli_kill()` function and `$mysqli->kill()`, in favour of using the `KILL` statement.

**Vote: Deprecate mysqli\_kill() and mysqli::kill()?** — Yes: 27 · No: 1 (closed)

### Deprecate the second parameter to mysqli\_store\_result()

- Author: Kamil Tekiela <dharman@php.net>
- Implementation: <https://github.com/php/php-src/pull/15311>

The `mysqli_store_result()` function used to have second parameter called `$mode`. As of PHP 8.1, this parameter is no longer used. As this parameter is due for removal in PHP 9.0 and users might unknowingly still use it, the proposal is to deprecate this parameter and the associated constant `MYSQLI_STORE_RESULT_COPY_DATA`. See <https://www.php.net/manual/en/mysqli.store-result.php>

**Vote: Deprecate the second parameter to mysqli\_store\_result()?** — Yes: 31 · No: 0 (closed)

### Deprecate lcg\_value()

- Author: Tim Düsterhus <timwolla@php.net>
- Implementation: <https://github.com/php/php-src/pull/15211>

The `lcg_value()` function is documented to return “A pseudo random float value between 0.0 and 1.0, inclusive” and also “lcg\_value() returns a pseudo random number in the range of (0, 1)”, the latter of which is generally understood as an open interval, excluding the boundary values, indicated by the use of round parentheses. This makes the documentation about the returned range contradict itself.

Looking at the implementation, the function is able to return one of 2147483562 different floats between `4.6566130000000002e-10` and `0.99999832898966134` (both inclusive). The returned floats are however *not* uniformly distributed within this interval, because the internal step size `4.6566128730773926e-10` that transform a randomly generated integer between 1 and 2147483562 into a float does not always result in a float that can be represented exactly, resulting in effective distances of `4.6566128730773926e-10` for most results, `4.6566139833004172e-10` for others and a much smaller distance of `1.2790449366306689e-08` between the highest possible return value and `1.0`.

The internally used “Combined LCG” RNG to generate the random integer between `1` and `2147483562` cannot be usefully be used for any other purpose, for example generating uniformly selected integers, either, because it cannot generate `0` and because the upper bound is not a value directly below a power of two, requiring expensive post-processing compared to the other engines available to userland (Mt19937, Xoshiro256StarStar, and PcgOneseq128XslRr64).

Furthermore the current implementation makes it possible for the seeding to generate degenerate internal states that either cut the period short, prevent some of results from being returned, or may generate a zero value.

The current state of the function makes it unfit for any serious usage, returning uniformly distributed results is the bare minimum one expects from a random number generator, unless a specific distribution is requested.

While it would be possible to fix the internal implementation as the RNG is not seedable from userland, this would technically still be a breaking change and it would not really improve the situation for the end user.

Even when the function would generate a uniformly generated integer between 0 and 1 (both excluded) to keep main semantics the current interval boundaries, the results would not be particularly useful. Expanding the values onto a larger interval would re-introduce a bias, as explained in the warning box on the [documentation page for ''\\Random\\Randomizer::nextFloat()''](https://www.php.net/manual/en/random-randomizer.nextfloat.php). Generating values from an open interval as a building block is also much less useful compared to a right-open interval that would include the lower bound as a possible return value.

Furthermore the function name is not particularly well-chosen. It does not indicate what the function does and references the underlying Combined LCG as an implementation detail within the `lcg_` prefix of the function name.

Since PHP 8.3, PHP provides `\Random\Randomizer::getFloat()` as a safe solution to generate uniformly distributed floats within arbitrary intervals.

As the function cannot be used in a safe way, except possibly for obscure use-cases, we propose the deprecation of it. It is possible to polyfill the functionality for users that rely on this peculiar behavior. An implementation based on the CSPRNG that avoids the issues of the Combined LCG would be as follows:

```php
function lcg_value(): float {
  return random_int(1, 2147483562) * 4.656613e-10;
}
```

**Vote: Deprecate lcg\_value()?** — Yes: 29 · No: 2 (closed)

### Deprecate uniqid()

- Author: Tim Düsterhus <timwolla@php.net>

The `uniqid()` function is documented to “Generate a unique ID”. The documentation further expands on this that the returned value is a “\[…\] timestamp based unique identifier as a string”. In other words, the `uniqid()` function is just a formatter for the current time.

While the `uniqid()` function makes sure to not generate the same timestamp for two consecutive calls, it nevertheless is incapable of actually guaranteeing that a unique ID is generated:

- Concurrent requests, for example by using multiple php-fpm workers on the same system, or when running the application on multiple servers, might call `uniqid()` at exactly the same point in time.
- An NTP client might move the clock backwards, for example if the hardware clock of the system in question is ticking too fast.

The function also takes a `$prefix` parameter, which as per the documentation may be used to, for example, ensure per-host IDs by adding a hostname prefix to every generated ID. This however does not protect against the clock moving backwards and is also hard to apply to separate multiple FPM workers within the same pool. It also requires manual effort on the user’s end to make the function safe to use.

Likewise the function also provides a `$more_entropy` parameter adding at most 32 bits of entropy to distinguish different values generated in the same microsecond. 32 bits of randomness is generally insufficient to guarantee uniqueness in the long term, especially if generated IDs are shared outside of a single application with other applications also leveraging `uniqid()`. As a comparison: The two behaviorally closest ID standards, UUIDv7 and ULIDs only use a timestamp with millisecond precision, but include 80 bits of randomness, resulting in 38 bits of effective additional randomness compared to `uniqid()`.

A GitHub search for `“uniqid()” language:PHP` reveals 136k results where `uniqid()` is not called with the `$more_entropy` parameter set to `true`, which is the bare minimum to consider the usage safe. Right on the first page of the results, a bare call to `uniqid()` is [used to generate a security-sensitive “email reset” token](https://github.com/HackerExperience/legacy/blob/5605b69400f9d91e951e71336e53c7040983d628/reset.php#L36) that is trivially guessable by knowing when the token was generated.

However even when specifying `$more_entropy` as `true`, `uniqid()` is often used in places where an *unguessable* rather than just a unique value is required. The previously mentioned “email reset” token would be such a place. Enumerating the 32 bits of randomness added is trivial for an attacker. Often complex, but ultimately meaningless, constructions, such as passing the output of `uniqid()` [through a hash function](https://github.com/manxoom/Ecommerce/blob/88b50675007ecc86bef8320e4be760e540c3277c/cart.php#L11), are used. The use of a hash function does not increase the unpredictability of the underlying value, because it cannot add entropy.

As users rely on `uniqid()`’s output format, it is not possible to adjust the behavior to make the function safer to use, except by adding more optional parameters that users will need to remember to add.

While there may be situations where `uniqid()` can safely be used, they are few and far between. The results of the GitHub search make it clear that users inappropriately use `uniqid()` for security-sensitive code, despite the warnings in the documentation. We expect most of them to be better served by using a purpose-built solution to safely generate a random string or random identifier.

This includes:

- `\bin2hex(\random_bytes(16))` to generate a printable and secure random string (e.g. an access token).
- The ramsey/uuid library to generate database identifiers.
- PHP’s `\Random\Randomizer::getBytesFromString()` method to generate random strings with a specific format.
- PHP’s `\DateTimeImmutable::format()` method to generate a time-based string when uniqueness is only a best-effort requirement.
- PHP’s `tempnam()` function to generate a filename for a temporary file. Incidentally the [amount of randomness of this function has been increased in PHP 8.4](https://github.com/php/php-src/pull/14364), to prevent a possible attack vector using guessable filenames.
- PHP’s `tmpfile()` function if just a temporary file handle (without knowing the filename) is required.

To gently nudge users away from `uniqid()` towards safer or more-standard alternatives in newly written code, we propose to deprecate `uniqid()`.

We acknowledge that there is a vast collection of existing code that uses `uniqid()`. While it is likely often the case that these usages are unsafe and should be replaced, this may not necessarily easy, due to consumers expecting a specific ID format. As such the removal of `uniqid()` will likely have a large impact on existing code to the point where users will hold off upgrading their PHP versions to not break their application.

As the internal implementation of `uniqid()` is low-maintenance and does not otherwise interact with the language’s behavior, keeping `uniqid()` available indefinitely is possible. Therefore we propose just a deprecation, **without any specific plans for the removal** of the `uniqid()` function. To ease planning on the user’s end, the `uniqid()` function shall remain available for at least 5 years or at least another full major version cycle, whichever is longer. This means it **may be removed in PHP 10 at the earliest** and the removal shall be part of a fresh RFC vote.

A polyfill (64 bit PHP only) is as follows:

```php
function my_uniqid(string $prefix = '', bool $more_entropy = false) {
	static $last = null;
	do {
		$microtime = \microtime();
	} while ($microtime === $last);
	$last = $microtime;
 
	[$usec, $sec] = \explode(" ", $microtime, 2);
	$usec = \substr($usec, 2);
	$usec %= 0x100000;
 
	if ($more_entropy) {
		$seed = (((float)random_int(0, 4294967295)) / 4294967295) * 10.0;
 
		return \sprintf("%s%08x%05x%.8F", $prefix, $sec, $usec, $seed);
	} else {
		return \sprintf("%s%08x%05x", $prefix, $sec, $usec);
	}
}
```

**Vote: Deprecate uniqid()?** — Yes: 14 · No: 23 (closed)

### Deprecate md5(), sha1(), md5\_file(), and sha1\_file()

- Author: Tim Düsterhus <timwolla@php.net>

The cryptographic checksum MD5 and SHA-1 are considered broken for their main use of verifying the authenticity of a a payload or message and should be replaced by a hash function from the SHA-2 family (e.g. SHA-256) or another cryptographic hash function that is still considered to be secure.

Unfortunately these cryptographically secure hash functions are only available by means of the generic `hash()` function (and the closely related `hash_init()`, `hash_file()`, and `hash_hmac` functions), making using them more verbose and thus seemingly more complicated than the standalone `md5()`, `sha1()`, `md5_file()`, and `sha1_file()` functions, which likely are available as standalone functions for historic versions only - the ext/hash extension is only required as of PHP 7.4 - and also do not support the incremental hashing by means of the `hash_init()` functionality.

To encourage users to use a secure hash functions, instead of using an insecure algorithm, because the code is shorter, we propose to deprecate standalone functions. This also keeps the documentation simpler, because these closely related functions do not each need to be explained by themselves and also slims down the list of functions in the standard library.

Users may replace the use of the standalone functions as follows if they still require the use of MD5 and SHA-1:

- `md5($data, $binary = false)` → `hash('md5', $data, $binary = false)`
- `sha1($data, $binary = false)` → `hash('sha1', $data, $binary = false)`
- `md5_file($filename, $binary = false)` → `hash_file('md5', $filename, $binary = false)`
- `sha1_file($filename, $binary = false)` → `hash_file('sha1', $filename, $binary = false)`

Only the standalone functions shall be deprecated. The MD5 and SHA-1 algorithm shall remain available without deprecations by means of the `hash()` function family. Despite being insecure for verifying the authenticity of a payload, there are use cases that are still considered secure and using the MD5 and SHA-1 algorithms might also be necessary for interoperability with existing legacy systems.

We acknowledge that there is a vast collection of existing code that uses these standalone functions. As such the removal of them will likely have a large impact on existing code, despite there being a direct replacement that can be automated with tools such as Rector or using IDE assistance.

As the internal implementation of these standalone functions is low-maintenance and does not otherwise interact with the language’s behavior, keeping them available indefinitely is possible. Therefore we propose just a deprecation, **without any specific plans for the removal** of the standalone functions. To ease planning on the user’s end, the standalone functions shall remain available for at least 5 years or at least another full major version cycle, whichever is longer. This means it **may be removed in PHP 10 at the earliest** and the removal shall be part of a fresh RFC vote.

**Vote: Deprecate md5(), sha1(), md5\_file(), and sha1\_file()?** — Yes: 18 · No: 21 (closed)

### Deprecate passing E\_USER\_ERROR to trigger\_error()

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15308>

Using `E_USER_ERROR` with `trigger_error()` triggers PHP's bailout mechanism, which means that it triggers the equivalent of a Fatal Error. This mechanism is generaly reserved for severe engine failures, such as being unable to allocate memory.

The problems of the bailout mechanism is explained in detail in the ["Issues with fatal errors" section of the Exceptions in the engine (for PHP 7)](https://externals.io/rfc/engine_exceptions_for_php7#issues_with_fatal_errors) RFC. Some of them are:

- `finally` blocks are not executed
- Destructors are not executed

Moreover, it is in theory possible to “catch” a E\_USER\_ERROR via an error handler defined with `set_error_handler()`by returning `true`, this is problematic as the execution will be returned to the code that called `trigger_error()`. Which it is unlikely to be able to handle.

Using exceptions instead solves all the above problems, and allows catching the error outside the problematic code path.

If the desired outcome is to terminate the program with no possible way to recover one should use the `exit()` function with a string argument.

Therefore we propose to deprecate passing `E_USER_ERROR` to `trigger_error()`

**Vote: Deprecate passing E\_USER\_ERROR to trigger\_error()** — Yes: 27 · No: 2 (closed)

### Deprecate using a single underscore ''\_'' as a class name

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15360>

Currently class names must be a valid label name (meaning they follow the same rules as variables and function names) and thus can start with an underscore `_`. It may also be \*just\* an underscore:

```php
class _ {}
```

The main motivation to deprecate using a single underscore `_` as a class name is that `_` conflicts with a potential wildcard pattern for the [Pattern Matching RFC](https://externals.io/rfc/pattern-matching), which is generally the token used for such a wildcard in other programming languages that support pattern matching.

The impact of this deprecation should be non-existent. An analysis using Exakat revealed that no one uses a class name of `_`.

**Vote: Deprecate using a single underscore as a class name?** — Yes: 28 · No: 7 (closed)

### Deprecate SOAP\_FUNCTIONS\_ALL constant and passing it to SoapServer::addFunction()

- Author: Gina Peter Banyard <girgias@php.net>
- Implementation: <https://github.com/php/php-src/pull/15310>

The `SOAP_FUNCTIONS_ALL` constant's sole purpose is to make all PHP functions available to client to use on the SOAP server.

This is of dubious use and potential security issue.

We therefore propose deprecating this function and passing an integer to `SoapServer::addFunction()` as the only valid integer value it accepts is `SOAP_FUNCTIONS_ALL`.

**Vote: Deprecate SOAP\_FUNCTIONS\_ALL constant and passing it to SoapServer::addFunction()?** — Yes: 28 · No: 1 (closed)

## Backward Incompatible Changes

For PHP 8.4 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.

### Constant SID

This was deprecated as part of [Deprecate GET/POST sessions](https://externals.io/rfc/deprecate-get-post-sessions) RFC.

### Deprecate E\_USER\_ERROR constant

This is removed to be tackled as a later point in time as not to affect the error\_reporting INI setting and corresponding function.
