Pages which need to be added/modified for complete documentation of PHP 8.6:
> […!NOTE]
> This issue is still a Work In Progress
> [!IMPORTANT]
> Priority should be given to documenting Core language and ext/standard behavioral changes
Source: https://github.com/php/php-src/blob/PHP-8.6/UPGRADING
## Migration Guide
- [ ] #5900
## Core
### Backward Incompatible Changes
- [ ] By-reference `foreach` loops may now visit previously skipped elements after array compaction. Internal pointers on deleted elements now move to the next surviving element during copy-on-write.
- [ ] `??`/`empty()` on a magic property no longer call `__get()` when `__isset()` has materialized the property by writing into the property table. The freshly-written value is returned directly. `isset()` is unaffected.
- [ ] `array_intersect()` with at least two arrays now converts values to strings while scanning its inputs instead of during sort comparisons. This can change the number and order of conversion warnings and `__toString()` calls, which conversion exception is reached, and the result for stateful `__toString()` implementations. Argument types are validated before checking for empty arrays or converting values. Values are not converted if any input array is empty.
- [ ] Form feed (`\f`) is now added to the default trimmed characters of `trim()`, `rtrim()` and `ltrim()`. RFC: https://wiki.php.net/rfc/trim_form_feed
- [ ] `base_convert()`, `bindec()`, `hexdec()` and `octdec()` now raise a notice when they cannot precisely convert the given number.
- [ ] `setlocale()`: arrays are now accepted only for the `$locales` argument. Passing an array as a later variadic locale argument now throws a `TypeError`. Passing any additional locale arguments when `$locales` is an array now throws an `ArgumentCountError`.
- [ ] `unpack()` now reads a `<` or `>` immediately following a format code as an endianness modifier rather than as the first character of the element name. Formats such as `"s<value"` now produce the key `"value"` instead of `"<value"`, and `"C>name"` raises a `ValueError` because the `C` format code accepts no endianness modifier. A name starting with these characters is unaffected when a repeater precedes it, as in `"s1<value"`. RFC: https://wiki.php.net/rfc/pack-unpack-endianness-signed-integers-support
- [ ] `fclose()`, `file_put_contents()` and `copy()` now return `false` when flushing or closing the stream fails. Previously such failures were silently ignored.
### Deprecations
- [ ] Using `namespace` as a class constant name is deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_namespace_as_a_class_constant_name
- [ ] Using the `return` statement in a `finally` block is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_returning_from_a_finally_block
- [ ] Specifying a return type of `array|null` / `?array` for `__debugInfo()` is now deprecated. Specify `array` instead.
- [ ] Returning values from `__construct()` and `__destruct()` is now deprecated. RFC: https://wiki.php.net/rfc/deprecate-return-value-from-construct
- [ ] Making `__construct()` and `__destruct()` a `Generator` is now deprecated. RFC: https://wiki.php.net/rfc/deprecate-return-value-from-construct
- [ ] Naming a function `readonly` is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_the_possibility_to_name_a_function_readonly
- [ ] Using `let` as the name of a class, interface, trait, enum, function, or constant (including via `define()`), as the alias passed to `class_alias()`, or as the alias name in a `use`, `use function`, or `use const` declaration is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_let_as_an_identifier
- [ ] Using `is` as the name of a class, interface, trait, enum, function, or constant (including via `define()`), as the alias passed to `class_alias()`, or as the alias name in a `use`, `use function`, or `use const` declaration is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_is_as_an_identifier
- [ ] Using `_` as a constant name (via `const` or `define()`), or as the alias name for a class or constant in a `use` declaration, is now deprecated. This extends the PHP 8.4 deprecation of `_` as a class name. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_using_as_a_constant_and_compile_time_alias
- [ ] Passing a 3rd argument to `define()` is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_define_with_case_insensitive_being_specified
- [ ] Calling `is_a()` with a string as the first argument when `$allow_string` is `false` is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_a_with_string_when_allow_string_is_false
- [ ] Calling `is_subclass_of()` with a string as the first argument when `$allow_string` is `false` is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_subclass_of_with_string_when_allow_string_is_false
- [ ] `metaphone()` is deprecated. Please use a userland phonetic matching library instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_metaphone_function
- [ ] Using more than 16 filters in a `php://filter` URL without configuring the `filter.max_filter_count` stream context option now emits an `E_DEPRECATED` warning. Use `stream_filter_append()` or configure this option explicitly. RFC: https://wiki.php.net/rfc/limit-maximum-number-of-filter-chains
- [ ] Passing an object to `array_walk()`/`array_walk_recursive()` is now deprecated. Use `get_object_vars()` on the object instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_array_parameter_of_array_walk_and_array_walk_recursive
- [ ] Passing an object as the `$data` argument to `http_build_query()` is now deprecated. The interpretation of object values within `$data` as arrays is also deprecated. Convert objects to arrays with `get_object_vars()` before calling the function. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_data_parameter_of_http_build_query
- [ ] The `is_double()` function is now deprecated. Use `is_float()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_double
- [ ] The `is_long()` functions are now deprecated. Use `is_int()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_long
- [ ] The `is_integer()` functions are now deprecated. Use `is_int()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_is_integer
- [ ] The `doubleval()` function is now deprecated. Use `floatval()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_doubleval
- [ ] The `strcoll()` function is now deprecated. Use `Collator::compare()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_strcoll
- [ ] The `SORT_LOCALE_STRING` constant for the family of sort functions is now deprecated. Use `Collator::sort()`, `Collator::asort()` or `Collator::sortWithSortKeys()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_sort_locale_string_flag_for_sort_functions
### INI changes
- [ ] Added the `error_include_args` INI option to make the display of function arguments consistent in errors; it is off by default. All parameters as actually passed to the function will be displayed, using the same infrastructure as stack traces (sensitive parameters are hidden, strings are truncated according to `zend.exception_string_param_max_len`). RFC: https://wiki.php.net/rfc/display_error_function_args
### New classes
- [ ] enum `SortDirection`. RFC: https://wiki.php.net/rfc/sort_direction_enum
- [ ] Stream errors API. RFC: https://wiki.php.net/rfc/stream_errors
- [ ] `StreamError`
- [ ] `StreamException`
- [ ] enum `StreamErrorStore`
- [ ] enum `StreamErrorMode`
- [ ] enum `StreamErrorCode`
- [ ] Polling API. RFC: https://wiki.php.net/rfc/poll_api
- [ ] `Io\Poll\Context`
- [ ] `Io\Poll\Watcher`
- [ ] enum `Io\Poll\Backend`
- [ ] enum `Io\Poll\Event`
- [ ] interface `Io\Poll\Handle`
- [ ] `StreamPollHandle`
- [ ] `Io\IoException`
- [ ] `Io\Poll\PollException`
- [ ] `Io\Poll\FailedPollOperationException`
- [ ] `Io\Poll\FailedContextInitializationException`
- [ ] `Io\Poll\FailedHandleAddException`
- [ ] `Io\Poll\FailedWatcherModificationException`
- [ ] `Io\Poll\FailedPollWaitException`
- [ ] `Io\Poll\BackendUnavailableException`
- [ ] `Io\Poll\InactiveWatcherException`
- [ ] `Io\Poll\HandleAlreadyWatchedException`
- [ ] `Io\Poll\InvalidHandleException`
### New functions
- [ ] `clamp()` returns the given value if in range, else returns the nearest bound. RFC: https://wiki.php.net/rfc/clamp_v2 (#4814)
- [ ] `stream_last_errors()`. RFC: https://wiki.php.net/rfc/stream_errors
- [ ] `stream_clear_errors()`. RFC: https://wiki.php.net/rfc/stream_errors
- [ ] `stream_socket_get_crypto_status()`
### New global constants
- [ ] `ARRAY_FILTER_USE_VALUE`
- [ ] `STREAM_CRYPTO_STATUS_NONE`
- [ ] `STREAM_CRYPTO_STATUS_WANT_READ`
- [ ] `STREAM_CRYPTO_STATUS_WANT_WRITE`
### New features
- [ ] Readonly properties may now declare default values. RFC: https://wiki.php.net/rfc/readonly_property_defaults
- [ ] It is now possible to use reference assignment on `WeakMap` without the key needing to be present beforehand.
- [ ] It is now possible to define the `__debugInfo()` magic method on enums. RFC: https://wiki.php.net/rfc/debugable-enums
- [ ] `#[\Override]` can now be applied to class constants, including enum cases. RFC: https://wiki.php.net/rfc/override_constants
- [ ] Partial function application. RFC: https://wiki.php.net/rfc/partial_function_application_v2
- [ ] Allow direct mutation of objects stored in constants or class constants via `OBJ->prop = $val`. RFC: https://wiki.php.net/rfc/const_object_property_write
- [ ] `pack()` and `unpack()` now accept the `<` and `>` endianness modifiers on the signed and unsigned integer format codes. RFC: https://wiki.php.net/rfc/pack-unpack-endianness-signed-integers-support
- [ ] `pack()` and `unpack()` now accept the `<` and `>` endianness modifiers on the float and double format codes. RFC: https://wiki.php.net/rfc/pack-unpack-float-endianness-modifier
### Changed functions
- [ ] `header_register_callback()` now declares `true` as its return type.
- [ ] `register_tick_function()` now declares `true` as its return type.
- [ ] `ini_get_all()` now includes a `"builtin_default_value"` element for each directive when `$details` is `true`. It holds the built-in default value of the directive (or `null` if it has none), independent of values set in php.ini, on the command line, or at runtime.
### Other changes
- [ ] In case of a hard OOM PHP now calls `abort()` instead of `exit(1)`, changing the exit code to 134 and possibly creating a core dump.
- [ ] The `PHP_OS_FAMILY` constant has an `AIX` value for when running on AIX or IBM i via PASE.
## Streams
- [ ] Added new stream errors API. It is controlled using the `error_mode`, `error_store` and `error_handler` stream context options. RFC: https://wiki.php.net/rfc/stream_errors
- [ ] Added the `filter.max_filter_count` stream context option for `php://filter` URLs. When set, opening the stream fails with a warning if the URL would add more filters than the configured value. Negative values disable the check. RFC: https://wiki.php.net/rfc/limit-maximum-number-of-filter-chains
- [ ] Added socket context option `so_reuseaddr` that allows disabling address reuse (`SO_REUSEADDR`) and explicitly uses `SO_EXCLUSIVEADDRUSE` on Windows.
- [ ] Added socket context options `so_keepalive`, `tcp_keepidle`, `tcp_keepintvl` and `tcp_keepcnt` that allow setting socket keepalive options.
- [ ] Added socket context option `so_linger` that sets `SO_LINGER` on TCP sockets. A positive value enables lingering for that many seconds, zero or a negative value disables it. Values above 65535 are clamped.
- [ ] Added socket context options `so_rcvbuf` and `so_sndbuf` that set the socket receive and send buffer sizes in bytes on TCP and UDP sockets. The value must be an integer between 1 and 2147483647; any other value makes the stream creation fail.
- [ ] Allowed casting filtered streams as file descriptors for select.
- [ ] Added the `write_seek_mode` filter parameter for the bz2, iconv, zlib, and string stream filters. It must be set via an associative array where the key is `"write_seek_mode"` and the value is one of `"preserve"`, `"reset"`, or `"strict"`.
## New warnings and exceptions
### Core (ext/standard)
- [ ] `array_filter()` now raises a `ValueError` when an invalid `$mode` argument value is passed.
- [ ] `array_change_key_case()` now raises a `ValueError` when an invalid `$case` argument value is passed.
- [ ] `getenv()` and `putenv()` now raise a `ValueError` when the first argument contains NUL bytes.
- [ ] `dl()` now raises a `ValueError` when the `$extension_filename` argument contains NUL bytes.
- [ ] `openlog()` now raises a `ValueError` when the `$prefix` argument contains NUL bytes.
- [ ] `parse_str()` now raises a `ValueError` when the `$string` argument contains NUL bytes.
- [ ] `setlocale()` now raises a `ValueError` when a locale name contains NUL bytes, instead of silently truncating it.
- [ ] `linkinfo()` now raises a `ValueError` when the `$path` argument is empty.
- [ ] `pathinfo()` now raises a `ValueError` when an invalid `$flags` argument value is passed.
- [ ] `scandir()` now raises a `ValueError` when an invalid `$sorting_order` argument value is passed.
- [ ] `number_format()` now raises a `ValueError` when `$decimals` is outside the integer range instead of silently clamping very large positive values.
- [ ] `sleep()` now raises a `ValueError` when `$seconds` is greater than the platform limit (`UINT_MAX` seconds, or `UINT_MAX / 1000` seconds on Windows) instead of allowing the value to overflow.
- [ ] `usleep()` now raises a `ValueError` when `$microseconds` is greater than `UINT_MAX` instead of allowing the value to overflow.
- [ ] `proc_open()` now raises a `ValueError` when the `$cwd` argument contains NUL bytes.
- [ ] The following functions now raise a `ValueError` when the `$filename` argument contains NUL bytes:
- [ ] `fileperms()`
- [ ] `fileinode()`
- [ ] `filesize()`
- [ ] `fileowner()`
- [ ] `filegroup()`
- [ ] `fileatime()`
- [ ] `filemtime()`
- [ ] `filectime()`
- [ ] `filetype()`
- [ ] `is_writable()`
- [ ] `is_readable()`
- [ ] `is_executable()`
- [ ] `is_file()`
- [ ] `is_dir()`
- [ ] `is_link()`
- [ ] `file_exists()`
- [ ] `lstat()`
- [ ] `stat()`
### Curl
- [ ] The callback registered with `CURLOPT_READFUNCTION` now throws a `ValueError` when returning an integer other than `0`, `CURL_READFUNC_ABORT` or `CURL_READFUNC_PAUSE`.
### DOM
- [ ] Array access on `Dom\DtdNamedNodeMap` objects now raises a `ValueError` when the integer index is greater than `INT_MAX` instead of overflowing to a smaller index.
### FTP
- [ ] `ftp_nb_fget()`, `ftp_nb_fput()`, `ftp_nb_get()` and `ftp_nb_put()` now throw an `Error` when the connection is already transferring, instead of emitting a warning and returning `false`.
### GD
- [ ] `imagesetstyle()`, `imagefilter()` and `imagecrop()` filter the types / values of their array arguments and raise a `TypeError` / `ValueError` accordingly.
- [ ] `imageaffinematrixget()` now enforces the documented `array|float` type for the `$options` parameter, including the corresponding weak and strict typing behavior.
### GMP
- [ ] `gmp_fact()` now throws a `ValueError` if `$num` does not fit into an unsigned long.
- [ ] `gmp_pow()`, `gmp_binomial()`, `gmp_root()` and `gmp_rootrem()` now throw a `ValueError` if their second argument does not fit into an unsigned long.
- [ ] The shift (`<<`, `>>`) and exponentiation (`**`) operators on GMP objects now throw a `ValueError` when GMP right operands are outside the unsigned long range, instead of silently truncating them.
- [ ] GMP integer string parsing now throws a `ValueError` for strings containing NUL bytes, instead of silently truncating them.
- [ ] `gmp_powm()` modulo-by-zero now raises a `DivisionByZeroError` whose message includes the function name and argument index (`$modulus`).
### Intl
- [ ] Passing a non-stringable object as a time zone to Intl APIs that accept time zone objects or strings now raises a `TypeError` instead of an `Error`.
- [ ] `IntlBreakIterator::getLocale()` now raises a `ValueError` when the type is neither `Locale::ACTUAL_LOCALE` nor `Locale::VALID_LOCALE` instead of returning `false`.
- [ ] `UConverter::transcode()` now rejects `from_subst` and `to_subst` option values longer than 127 bytes instead of silently truncating the length before passing it to ICU.
- [ ] `IntlDateFormatter::parse()`/`datefmt_parse()` and `IntlDateFormatter::localtime()`/`datefmt_localtime()` now raise a `TypeError` when the offset argument is not of type int instead of silently converting the value.
- [ ] `Collator::sort()`, `collator_sort()`, `Collator::asort()`, and `collator_asort()` now report UTF-8/UTF-16 conversion failures during comparison through the intl error mechanism and return `false`. With `intl.use_exceptions` enabled, these failures throw `IntlException`. Previously, these paths emitted a warning and compared the value as an empty string.
### PCNTL
- [ ] `pcntl_alarm()` now raises a `ValueError` if the seconds argument is lower than zero or greater than the platform's `UINT_MAX`.
- [ ] `pcntl_exec()` now raises a `ValueError` if the `$args` argument is not a list array.
### PGSQL
- [ ] `pg_fetch_object()` now reports the `ValueError` for a non-empty `$constructor_args` on a class without a constructor on the `$constructor_args` argument instead of `$class`. Errors raised when the requested class is not instantiable (abstract, interface, enum) now surface before the row is fetched.
### Phar
- [ ] `Phar::mungServer()` now raises a `ValueError` when an invalid argument value is passed instead of being silently ignored.
- [ ] `Phar::addEmptyDir()` now rejects `"/.phar"` paths in addition to `".phar"` paths, and raises the same `BadMethodCallException` for attempts to create the reserved magic `".phar"` directory through that form.
### Session
- [ ] Setting `session.cookie_path`, `session.cookie_domain`, or `session.cache_limiter` to a value containing NUL bytes now emits a warning and leaves the setting unchanged.
- [ ] A `ValueError` is thrown if `$name` is a string containing NUL bytes in `session_module_name()`.
### Shmop
- [ ] `shmop_open()` now raises a `ValueError` when the `$key` argument is outside the platform's `key_t` range instead of passing a truncated key to the operating system.
### SimpleXML
- [ ] `SimpleXMLElement::__construct()` now raises a `ValueError` when the `$data` argument contains NUL bytes, matching `simplexml_load_file()`.
### SOAP
- [ ] `SoapClient` now throws `TypeError` for non-array `"classmap"` options and `ValueError` for arrays containing integer keys, also when the `"exceptions"` option is disabled.
### Sockets
- [ ] `socket_set_option()` with `SO_ATTACH_REUSEPORT_CBPF` now requires an int `$value` and a `$level` of `SOL_SOCKET`. Any other value type throws a `TypeError` instead of being coerced, and any other level raises a warning and returns `false`.
### Sodium
- [ ] `sodium_crypto_pwhash()`, `sodium_crypto_pwhash_str()`, `sodium_crypto_pwhash_scryptsalsa208sha256()` and `sodium_crypto_pwhash_scryptsalsa208sha256_str()` now throw `ValueError` instead of `SodiumException` when an argument is out of range, such as an opslimit or memlimit below the documented minimum. `SodiumException` is still thrown for internal libsodium failures.
### SPL
- [ ] `SplObjectStorage::getHash()` implementations may no longer mutate any `SplObjectStorage` instance. Attempting to do so now throws an `Error`.
### Sysvshm
- [ ] `shm_attach()` now raises a `ValueError` when the `$key` argument is outside the platform's `key_t` range instead of passing a truncated key to the operating system.
### Zip
- [ ] `ZipArchive::extractTo()` now raises a `TypeError` for the files argument if one or more of the entries is not a string.
- [ ] `ZipArchive::addGlob()` and `ZipArchive::addPattern()` now raise a `TypeError` when the `"remove_all_path"` option is not of type bool, or when the `"comp_method"`, `"comp_flags"`, or `"enc_method"` options are not of type int (numeric strings are coerced), instead of emitting a warning.
- [ ] Serializing or unserializing a `ZipArchive` now throws an `Exception`. A subclass can override `__serialize()` and `__unserialize()` to round-trip through `ZipArchive::closeString()` and `ZipArchive::openString()`.
### Zlib
- [ ] `deflate_init()` now raises a `TypeError` when the value for option `"level"`, `"memory"`, `"window"`, or `"strategy"` is not of type int.
- [ ] `inflate_init()` now raises a `TypeError` when the value for option `"window"` is not of type int.
## SAPI changes
### CLI
- [ ] The built-in development server now accepts requests using the HTTP `QUERY` method instead of returning 501 Not Implemented.
- [ ] The built-in development server no longer reflects the `Host` header from requests.
## Windows support
- [ ] The official Windows builds now use Visual Studio 2026 (VS18).
- [ ] The libxml2 library used by the official Windows builds has been upgraded to version 2.15.3. As a result, `DOMDocument::$documentURI` for documents loaded from a local file now contains a native filesystem path instead of a file URI.
- [ ] The OpenSSL library used by the official Windows builds has been upgraded to OpenSSL 4.
## Extension changes
### BZ2
- [ ] Deprecations
- [ ] Passing an object for the Bzip2 {de}compression stream filter is now deprecated. Use `get_object_vars()` on the object instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_as_parameters_to_the_bzip2decompress_and_bzip2compress_stream_filters
### COM
- [ ] BC breaks
- [ ] It is no longer possible to clone `variant` objects because the cloning behavior was ill-defined.
### Curl
- [ ] New global constants
- [ ] `CURLINFO_SIZE_DELIVERED` (libcurl >= 8.20.0).
- [ ] `CURLOPT_SEEKFUNCTION`.
- [ ] `CURL_SEEKFUNC_OK`.
- [ ] `CURL_SEEKFUNC_FAIL`.
- [ ] `CURL_SEEKFUNC_CANTSEEK`.
- [ ] `CURL_READFUNC_ABORT`.
- [ ] Other changes
- [ ] `curl_getinfo()` return array now includes a new `size_delivered` key, which indicates the total number of bytes passed to the download write callback. This value can also be obtained by passing `CURLINFO_SIZE_DELIVERED` as the `$option` parameter. Requires libcurl 8.20.0 or later.
- [ ] Added `CURLOPT_SEEKFUNCTION` to register a callback that repositions a streamed request body so libcurl can rewind and resend it on a redirect, multi-pass authentication, or a retried reused connection instead of failing with `CURLE_SEND_FAIL_REWIND`. The callback receives the `CurlHandle`, offset and origin, and must return one of `CURL_SEEKFUNC_OK`, `CURL_SEEKFUNC_FAIL` or `CURL_SEEKFUNC_CANTSEEK`.
### Date
- [ ] New classes
- [ ] `Time\Duration`. RFC: https://wiki.php.net/rfc/duration_class
- [ ] `Time\TimeException`. RFC: https://wiki.php.net/rfc/duration_class
- [ ] Other changes
- [ ] The following methods now have tentative `static` return types: `DateTime::createFromInterface()`, `DateTimeImmutable::__set_state()`, `DateTimeImmutable::modify()`, `DateTimeImmutable::add()`, `DateTimeImmutable::sub()`, `DateTimeImmutable::setTimezone()`, `DateTimeImmutable::setTime()`, `DateTimeImmutable::setDate()`, `DateTimeImmutable::setISODate()`, `DateTimeImmutable::setTimestamp()`, `DateTimeImmutable::createFromInterface()`, `DateTimeZone::__set_state()`, `DateInterval::__set_state()`, `DatePeriod::__set_state()`.
### DOM
- [ ] BC breaks
- [ ] Properties previously documented as `@readonly` (e.g. `DOMNode::$nodeType`, `DOMDocument::$xmlEncoding`, `DOMEntity::$actualEncoding`, `DOMEntity::$encoding`, `DOMEntity::$version`) are now declared with asymmetric visibility (`public private(set)`). Attempts to write to them from outside the class now raise "Cannot modify private(set) property" instead of the prior readonly modification error. `ReflectionProperty::isWritable()` also reports these properties accurately.
- [ ] Array access on `Dom\DtdNamedNodeMap` objects now returns `null` for negative integer indexes instead of returning the first node.
### Fileinfo
- [ ] Other changes
- [ ] `finfo_file()` now works with remote streams.
- [ ] Upgraded to file 5.48. Custom compiled magic databases from older file versions must be regenerated.
### Filter
- [ ] Other changes
- [ ] `filter_var_array()` return type has been narrowed from `array|false|null` to `array|false`. `filter_input_array()` is unaffected: it still returns `null` when the requested superglobal does not exist.
### GMP
- [ ] Deprecations
- [ ] The shift (`<<`, `>>`) and exponentiation (`**`) operators on GMP objects now emit a deprecation warning when converting a float right operand to int loses precision.
- [ ] New functions
- [ ] `gmp_powm_sec()` for side-channel quiet modular exponentiation. Requires GNU MP 5.0.0 or later; it is not available on official Windows builds using MPIR.
- [ ] `gmp_prevprime()` to get the largest prime smaller than the given number. The optional `$definitely_prime` output parameter indicates whether the returned number is definitely prime, as opposed to probably prime. A `ValueError` is thrown if no such prime exists. Requires GNU MP 6.3.0 or later; it is not available on official Windows builds using MPIR.
### Hash
- [ ] Other changes
- [ ] The bundled version of xxHash was upgraded to 0.8.2.
### Intl
- [ ] BC breaks
- [ ] `IntlIterator::current()` now returns `null` when called before the iterator is positioned, or after the iterator becomes invalid, instead of exposing an undefined value.
- [ ] `MessageFormatter::parse()` and `MessageFormatter::parseMessage()` now return `PHP_INT_MIN` as int, rather than float, on 64-bit platforms when parsing integer values.
- [ ] The `$type` parameter of `IntlBreakIterator::getPartsIterator()` has been changed from string to int to match the underlying implementation.
- [ ] `ResourceBundle::get()` and `resourcebundle_get()` now report fallback-disabled resource lookups with "without fallback to <locale>" instead of the malformed "without fallback from to <locale>".
- [ ] New classes
- [ ] `IntlNumberRangeFormatter` to format an interval of two numbers with a given skeleton, locale, `IntlNumberRangeFormatter::COLLAPSE_*` collapse and `IntlNumberRangeFormatter::IDENTITY_FALLBACK_*` identity fallbacks. It is supported as of ICU 63.
- [ ] New functions
- [ ] `grapheme_strrev()`. RFC: https://wiki.php.net/rfc/grapheme_strrev
- [ ] `IntlDatePatternGenerator::getSkeleton()` (static)
- [ ] `IntlDatePatternGenerator::getBaseSkeleton()` (static)
- [ ] `Locale::getDisplayKeyword()` / `locale_get_display_keyword()`. RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue
- [ ] `Locale::getDisplayKeywordValue()` / `locale_get_display_keyword_value()`. RFC: https://wiki.php.net/rfc/getdisplaykeyword_and_getdisplaykeywordvalue
- [ ] `SpoofChecker::areBidiConfusable()` to check whether two strings are confusable for a given text direction. Supported as of ICU 74.
- [ ] `SpoofChecker::getBidiSkeleton()` to generate a confusable skeleton for a given text direction. Supported as of ICU 74.
- [ ] `SpoofChecker::getSkeleton()` to generate a confusable skeleton for a given string.
- [ ] New class constants
- [ ] `SpoofChecker::LTR` and `SpoofChecker::RTL`.
### JSON
- [ ] Other changes
- [ ] Added extra info about error location to the JSON error messages returned from `json_last_error_msg()` and the `JsonException` message.
### LDAP
- [ ] Other changes
- [ ] `ldap_free_result()` return type has been narrowed from `bool` to `true`.
### MBstring
- [ ] BC breaks
- [ ] Unicode data tables have been updated to Unicode 18.0.
- [ ] Deprecations
- [ ] Mbregex has been deprecated, because the underlying Oniguruma library is no longer maintained. RFC: https://wiki.php.net/rfc/eol-oniguruma
- [ ] Passing objects to `mb_convert_variables()` is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_vars_parameter_of_mb_convert_variables
- [ ] INI changes
- [ ] The `mbstring.detect_order` INI directive now updates the internal detection order when changed at runtime via `ini_set()`. Setting the directive to `NULL` or an empty string at runtime now leaves the previously configured detection order unchanged.
### MySQLi
- [ ] Deprecations
- [ ] The `mysqli_get_charset()` function and `mysqli::get_charset()` method are now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_mysqli_get_charset
- [ ] The `mysqli_stmt_init()` function, `mysqli::stmt_init()` method, and calling the `mysqli_stmt` constructor without providing the `$query` parameter are now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_mysqlistmt_init
- [ ] INI changes
- [ ] `mysqli.default_port` now checks the validity of the value which should be between 0 and 65535 inclusive.
- [ ] New functions
- [ ] `mysqli::quote_string()` / `mysqli_quote_string()`. RFC: https://wiki.php.net/rfc/mysqli_quote_string
- [ ] New global constants
- [ ] `MYSQLI_OPT_COMPRESS`.
- [ ] Other changes
- [ ] The return structure of `mysqli_get_charset()` no longer contains the undocumented `"comment"` element. The value of `"charsetnr"` is now set to a constant `0`.
### Opcache
- [ ] INI changes
- [ ] `opcache.jit_debug` accepts a new flag: `ZEND_JIT_DEBUG_TRACE_EXIT_INFO_SRC`. When used along with `ZEND_JIT_DEBUG_TRACE_EXIT_INFO`, the source of exit points is printed in exit info output, in debug builds.
- [ ] Other changes
- [ ] JIT is now supported for ZTS builds on Apple Silicon.
### OpenSSL
- [ ] New classes
- [ ] `Openssl\OpensslException`
- [ ] `Openssl\Session`. RFC: https://wiki.php.net/rfc/tls_session_resumption
- [ ] `Openssl\Psk`
- [ ] New global constants
- [ ] `OPENSSL_RSA_PSS_SALTLEN_DIGEST`.
- [ ] `OPENSSL_RSA_PSS_SALTLEN_AUTO`.
- [ ] `OPENSSL_RSA_PSS_SALTLEN_MAX`.
- [ ] Other changes
- [ ] Added TLS session resumption support for streams with new stream context options: `session_data`, `session_new_cb`, `session_cache`, `session_cache_size`, `session_timeout`, `session_id_context`, `session_get_cb`, `session_remove_cb`, and `num_tickets`. RFC: https://wiki.php.net/rfc/tls_session_resumption
- [ ] Added TLS external PSK support for streams with new stream context options: `psk_client_cb` and `psk_server_cb`.
- [ ] Added TLS 1.3 early data (0-RTT) support for streams. Clients send early data with the `early_data` context option; servers accept it with `max_early_data` and receive it through the `early_data_cb` callback. The outcome is reported as `'accepted'`, `'rejected'` or `'not_sent'` in the `early_data` key of the crypto `stream_get_meta_data()` array.
- [ ] Output of `openssl_x509_parse()` contains `criticalExtensions` listing all critical certificate extensions.
- [ ] `openssl_sign()` and `openssl_verify()` now have an additional optional argument `$salt_length` that allows controlling the RSA-PSS salt length when `OPENSSL_PKCS1_PSS_PADDING` is used. It accepts an explicit length or one of the new `OPENSSL_RSA_PSS_SALTLEN_*` constants.
### PCRE
- [ ] BC breaks
- [ ] `preg_grep()` now returns `false` instead of a partial array when a PCRE execution error occurs (e.g. malformed UTF-8 input with the `/u` modifier). This is consistent with other `preg_*` functions.
### PDO_DBLIB
- [ ] Other changes
- [ ] When using persistent connections, there is now a liveness check in the constructor.
### PDO_PGSQL
- [ ] New class constants
- [ ] `Pdo\Pgsql::ATTR_CHUNK_SIZE`, the number of rows a statement fetches per chunk. A value of 1 or more enters the lazy fetch mode of `PDO::ATTR_PREFETCH => 0`. Setting `PDO::ATTR_PREFETCH` replaces the chunk size. Statements that are prepared with neither it nor `PDO::ATTR_PREFETCH` fall back to the value set on the connection. Requires libpq 17 or later.
### Phar
- [ ] BC breaks
- [ ] `Phar::addEmptyDir()` now treats non-magic names that merely share the `".phar"` prefix as ordinary directories.
- [ ] Files are only automatically interpreted as Phar archives when included if `".phar"` occurs as an extension in the filename component of their paths. Previously, it could occur in a directory name or as part of an extension such as `".pharma"`.
- [ ] Other changes
- [ ] Overriding the `getMTime()` and `getPathname()` methods of `SplFileInfo` now influences the result of the phar `buildFrom` family of functions. This makes it possible to override the timestamp and names of files.
- [ ] `Phar::mungServer()` now supports reference values.
### Readline
- [ ] Other changes
- [ ] `readline_completion_function()` now declares `true` as its return type.
### Reflection
- [ ] Deprecations
- [ ] Calling `ReflectionProperty::setValue()` with an object that is not an instance of the class on which the property was declared is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionpropertysetvalue_and_reflectionpropertysetrawvalue_with_wrong_types
- [ ] Calling `ReflectionProperty::setRawValue()` with an object that is not an instance of the class on which the property was declared is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionpropertysetvalue_and_reflectionpropertysetrawvalue_with_wrong_types
- [ ] Calling `ReflectionMethod::invoke()` or `ReflectionMethod::invokeArgs()` with an object and a static method is now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_reflectionmethodinvoke_and_reflectionmethodinvokeargs_with_objects_for_static_methods
- [ ] New functions
- [ ] `ReflectionConstant::inNamespace()`
- [ ] `ReflectionProperty::isReadable()`. RFC: https://wiki.php.net/rfc/isreadable-iswriteable
- [ ] `ReflectionProperty::isWritable()`. RFC: https://wiki.php.net/rfc/isreadable-iswriteable
- [ ] `ReflectionParameter::getDocComment()`. RFC: https://wiki.php.net/rfc/parameter-doccomments
- [ ] `ReflectionAttribute::inNamespace()`
- [ ] `ReflectionAttribute::getNamespaceName()`
- [ ] `ReflectionAttribute::getShortName()`
- [ ] Other changes
- [ ] The outputs of `ReflectionClassConstant::__toString()` and `ReflectionConstant::__toString()` for constants with boolean values have been changed to use `true` and `false` rather than `1` and an empty string. This also affects other ways of printing class constants, e.g. `ReflectionClass::__toString()`.
### Session
- [ ] BC breaks
- [ ] `session_encode()` now returns an empty string instead of `false` for empty sessions. It only returns `false` now when the session data could not be encoded (mainly with the default serialization handler if a key contains the pipe `|` character).
- [ ] When `session.lazy_write` is enabled and a session handler implements `SessionUpdateTimestampHandlerInterface`, sessions that were read as empty and remain empty at write time will now trigger `updateTimestamp()` instead of `write()`. Custom session handlers that rely on `write()` being called with empty data (e.g. to destroy the session) should implement the same logic in their `updateTimestamp()` method.
- [ ] `SessionHandler::validateId()` has been added and delegates to the configured save handler. A subclass that declares `validateId()` without a return type now emits a deprecation notice for the tentative `bool` return type. A subclass that overrides `open()` without calling `parent::open()` keeps its previous behavior and emits a warning when an ID is validated.
- [ ] INI changes (RFC: https://wiki.php.net/rfc/session_security_defaults)
- [ ] `session.use_strict_mode` default is now `1` (was `0`). Custom session handlers that previously relied on accepting externally supplied IDs without a corresponding storage entry must either implement `validateId()` / `create_sid()` or explicitly set this to `0`.
- [ ] `session.cookie_httponly` default is now `1` (was `0`). Applications that read the session cookie from JavaScript must explicitly set this to `0`.
- [ ] `session.cookie_samesite` default is now `"Lax"` (was unset). Applications that depend on session cookies being sent on cross-site POST submissions must explicitly set this to `"None"` (and also set `session.cookie_secure` to `1`).
- [ ] New functions
- [ ] `SessionHandler::validateId()`
- [ ] Deprecations
- [ ] It is now deprecated to pass an object that does not implement the `create_sid()` and `validateId()` methods to `session_set_save_handler()`. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_passing_a_sessionhandler_object_to_session_set_save_handler_which_does_not_contain_the_create_sid_and_validateid
- [ ] A deprecation is now emitted when implementing `SessionHandlerInterface` on a class which doesn't define the `create_sid()` or `validateId()` methods, as those will be moved from `SessionUpdateTimestampHandlerInterface` and `SessionIdInterface` to `SessionHandlerInterface`. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_passing_a_sessionhandler_object_to_session_set_save_handler_which_does_not_contain_the_create_sid_and_validateid
### SNMP
- [ ] New classes
- [ ] enum `Snmp\Mib`
- [ ] enum `Snmp\OidOutput`
- [ ] enum `Snmp\Output`
- [ ] enum `Snmp\StringOutput`
- [ ] New functions
- [ ] `snmp_init_mib()` to reset the MIB tree. RFC: https://wiki.php.net/rfc/snmp_improvements_2026#allow_the_snmp_mib_to_be_reset
- [ ] `snmp_set_mib_option()`. RFC: https://wiki.php.net/rfc/snmp_improvements_2026#implement_more_mib_parsing_and_value_output_controls
- [ ] `snmp_set_output_option()`
- [ ] `snmp_set_string_output_format()`
- [ ] `SNMP::setOidOutputFormat()`
- [ ] `SNMP::setStringOutputFormat()`
- [ ] New properties
- [ ] `SNMP::$numeric_index`, `SNMP::$numeric_timeticks`, `SNMP::$extended_index`, `SNMP::$dont_print_units`, `SNMP::$escape_quotes`, `SNMP::$print_hex_text`
- [ ] Other changes
- [ ] It is now possible to use AES192, AES192C, AES256, and AES256C as SNMPv3 security protocols if the underlying library supports them. RFC: https://wiki.php.net/rfc/snmp_improvements_2026#increase_the_number_of_snmpv3_security_protocols_supported
### SOAP
- [ ] BC breaks
- [ ] The `"classmap"` option of `SoapClient` and `SoapServer` now rejects arrays containing integer keys. Previously, sparse integer-keyed and mixed-keyed arrays could be accepted.
- [ ] WSDL/XML Schema parsing now rejects out-of-range integer values for occurrence constraints and integer restriction facets. Negative `minOccurs` and `maxOccurs` values are rejected as well.
- [ ] SOAP encoding errors now report the affected type or failing operation in the error message instead of the generic "Encoding: Violation of encoding rules" message.
### Sockets
- [ ] BC breaks
- [ ] `socket_set_option()` with `SO_ATTACH_REUSEPORT_CBPF` and a `$value` of `0` now detaches the reuseport filter through `SO_DETACH_REUSEPORT_BPF`. It previously used `SO_DETACH_BPF`, which left the reuseport program attached.
- [ ] New global constants
- [ ] `TCP_USER_TIMEOUT` (Linux only).
- [ ] `AF_UNSPEC`.
- [ ] `EAI_BADFLAGS`.
- [ ] `EAI_NONAME`.
- [ ] `EAI_AGAIN`.
- [ ] `EAI_FAIL`.
- [ ] `EAI_NODATA`.
- [ ] `EAI_FAMILY`.
- [ ] `EAI_SOCKTYPE`.
- [ ] `EAI_SERVICE`.
- [ ] `EAI_ADDRFAMILY`.
- [ ] `EAI_SYSTEM`.
- [ ] `EAI_OVERFLOW`.
- [ ] `EAI_INPROGRESS`.
- [ ] `EAI_CANCELED`.
- [ ] `EAI_NOTCANCELED`.
- [ ] `EAI_ALLDONE`.
- [ ] `EAI_INTR`.
- [ ] `EAI_IDN_ENCODE`.
- [ ] `SO_DETACH_REUSEPORT_BPF` (Linux only).
- [ ] Other changes
- [ ] `socket_addrinfo_lookup()` now has an additional optional argument `$error_code` that, when not `null`, receives the error code on failure (one of the `EAI_*` constants).
- [ ] `socket_cmsg_space()` return type has been narrowed from `?int` to `int`.
### Sodium
- [ ] New functions
- [ ] IPCrypt
- [ ] `sodium_crypto_ipcrypt_keygen()`
- [ ] `sodium_crypto_ipcrypt_encrypt()`
- [ ] `sodium_crypto_ipcrypt_decrypt()`
- [ ] `sodium_crypto_ipcrypt_nd_keygen()`
- [ ] `sodium_crypto_ipcrypt_nd_encrypt()`
- [ ] `sodium_crypto_ipcrypt_nd_decrypt()`
- [ ] `sodium_crypto_ipcrypt_ndx_keygen()`
- [ ] `sodium_crypto_ipcrypt_ndx_encrypt()`
- [ ] `sodium_crypto_ipcrypt_ndx_decrypt()`
- [ ] `sodium_crypto_ipcrypt_pfx_keygen()`
- [ ] `sodium_crypto_ipcrypt_pfx_encrypt()`
- [ ] `sodium_crypto_ipcrypt_pfx_decrypt()`
- [ ] `sodium_bin2ip()`
- [ ] `sodium_ip2bin()`
- [ ] XOF
- [ ] `sodium_crypto_xof_shake128()`
- [ ] `sodium_crypto_xof_shake128_init()`
- [ ] `sodium_crypto_xof_shake128_update()`
- [ ] `sodium_crypto_xof_shake128_squeeze()`
- [ ] `sodium_crypto_xof_shake256()`
- [ ] `sodium_crypto_xof_shake256_init()`
- [ ] `sodium_crypto_xof_shake256_update()`
- [ ] `sodium_crypto_xof_shake256_squeeze()`
- [ ] `sodium_crypto_xof_turboshake128()`
- [ ] `sodium_crypto_xof_turboshake128_init()`
- [ ] `sodium_crypto_xof_turboshake128_update()`
- [ ] `sodium_crypto_xof_turboshake128_squeeze()`
- [ ] `sodium_crypto_xof_turboshake256()`
- [ ] `sodium_crypto_xof_turboshake256_init()`
- [ ] `sodium_crypto_xof_turboshake256_update()`
- [ ] `sodium_crypto_xof_turboshake256_squeeze()`
- [ ] X-Wing KEM (hybrid ML-KEM768+X25519, libsodium >= 1.0.22)
- [ ] `sodium_crypto_kem_keypair()`
- [ ] `sodium_crypto_kem_seed_keypair()`
- [ ] `sodium_crypto_kem_secretkey()`
- [ ] `sodium_crypto_kem_publickey()`
- [ ] `sodium_crypto_kem_enc()`
- [ ] `sodium_crypto_kem_dec()`
- [ ] ML-KEM768 (FIPS 203) KEM (libsodium >= 1.0.22)
- [ ] `sodium_crypto_kem_mlkem768_keypair()`
- [ ] `sodium_crypto_kem_mlkem768_seed_keypair()`
- [ ] `sodium_crypto_kem_mlkem768_secretkey()`
- [ ] `sodium_crypto_kem_mlkem768_publickey()`
- [ ] `sodium_crypto_kem_mlkem768_enc()`
- [ ] `sodium_crypto_kem_mlkem768_dec()`
- [ ] New global constants
- [ ] `SODIUM_CRYPTO_IPCRYPT_BYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_KEYBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_ND_KEYBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_ND_TWEAKBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_ND_INPUTBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_ND_OUTPUTBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_NDX_KEYBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_NDX_TWEAKBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_NDX_INPUTBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_NDX_OUTPUTBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_PFX_KEYBYTES`
- [ ] `SODIUM_CRYPTO_IPCRYPT_PFX_BYTES`
- [ ] `SODIUM_CRYPTO_XOF_SHAKE128_BLOCKBYTES`
- [ ] `SODIUM_CRYPTO_XOF_SHAKE128_STATEBYTES`
- [ ] `SODIUM_CRYPTO_XOF_SHAKE256_BLOCKBYTES`
- [ ] `SODIUM_CRYPTO_XOF_SHAKE256_STATEBYTES`
- [ ] `SODIUM_CRYPTO_XOF_TURBOSHAKE128_BLOCKBYTES`
- [ ] `SODIUM_CRYPTO_XOF_TURBOSHAKE128_STATEBYTES`
- [ ] `SODIUM_CRYPTO_XOF_TURBOSHAKE256_BLOCKBYTES`
- [ ] `SODIUM_CRYPTO_XOF_TURBOSHAKE256_STATEBYTES`
- [ ] `SODIUM_CRYPTO_KEM_PUBLICKEYBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_SECRETKEYBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_CIPHERTEXTBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_SHAREDSECRETBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_SEEDBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_KEYPAIRBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_PUBLICKEYBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_SECRETKEYBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_CIPHERTEXTBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_SHAREDSECRETBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_SEEDBYTES` (libsodium >= 1.0.22)
- [ ] `SODIUM_CRYPTO_KEM_MLKEM768_KEYPAIRBYTES` (libsodium >= 1.0.22)
### SPL
- [ ] BC breaks
- [ ] `SplFileObject::next()` now advances the stream when no prior `current()` call has cached a line. A subsequent `current()` call returns the new line rather than the previous one.
- [ ] `SplFileObject::fgets()` no longer caches the returned line for subsequent `current()` calls. `current()` now re-reads from the current stream position instead of returning the line `fgets()` just returned.
- [ ] `SplFileObject::next()` past EOF no longer increments `key()` without bound. `SplFileObject::seek()` past EOF now produces the same `key()` value as `SplTempFileObject`; the two previously returned different values.
- [ ] `DirectoryIterator::key()` now returns `int|string`, and `DirectoryIterator::current()` returns `string|SplFileInfo|static`.
- [ ] Deprecations
- [ ] The `spl_classes()` function is now deprecated. Use `ReflectionExtension::getClassNames()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_spl_classes
- [ ] The `spl_object_hash()` function is now deprecated. Use `spl_object_id()` instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_spl_object_hash
- [ ] The following `ArrayIterator` methods are now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_arrayiterator_methods_that_inherit_arrayobject_implementation
- [ ] `ArrayIterator::getFlags()`
- [ ] `ArrayIterator::setFlags()`
- [ ] `ArrayIterator::asort()`
- [ ] `ArrayIterator::ksort()`
- [ ] `ArrayIterator::uasort()`
- [ ] `ArrayIterator::uksort()`
- [ ] `ArrayIterator::natsort()`
- [ ] `ArrayIterator::natcasesort()`
- [ ] `ArrayIterator::unserialize()`
- [ ] `ArrayIterator::serialize()`
- [ ] The following `SplFileObject` methods are now deprecated. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_splfileobject_csv_methods
- [ ] `SplFileObject::fgetcsv()`
- [ ] `SplFileObject::fputcsv()`
- [ ] `SplFileObject::setCsvControl()`
- [ ] `SplFileObject::getCsvControl()`
### URI
- [ ] BC breaks
- [ ] `Uri\WhatWg\Url::__construct()` now sets `$softErrors` to an empty array when URL processing throws an exception, instead of preserving its value. URL validation errors remain available in the `Uri\WhatWg\InvalidUrlException::$errors` property.
- [ ] New classes
- [ ] `Uri\Rfc3986\UriBuilder`. RFC: https://wiki.php.net/rfc/uri_followup#uri_building
- [ ] `Uri\WhatWg\UrlBuilder`. RFC: https://wiki.php.net/rfc/uri_followup#uri_building
- [ ] enum `Uri\WhatWg\UrlPercentEncodingMode`. RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support
- [ ] New functions
- [ ] `Uri\Rfc3986\Uri::getUriType()`. RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection
- [ ] `Uri\WhatWg\Url::isSpecialScheme()`. RFC: https://wiki.php.net/rfc/uri_followup#uri_type_detection
- [ ] `Uri\Rfc3986\Uri::getHostType()`. RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection
- [ ] `Uri\WhatWg\Url::getHostType()`. RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection
- [ ] `Uri\WhatWg\url_percent_encode()`. RFC: https://wiki.php.net/rfc/uri_followup#percent-encoding_support
### Zip
- [ ] New functions
- [ ] `ZipArchive::openString()`
- [ ] `ZipArchive::closeString()`
- [ ] Other changes
- [ ] `zip_entry_close()` return type has been narrowed from `bool` to `true`.
### Zlib
- [ ] Deprecations
- [ ] Passing an object for the zlib deflate and inflate stream filter is now deprecated. Use `get_object_vars()` on the object instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_as_parameters_to_the_zlibinflate_and_zlibdeflate_stream_filters
- [ ] Passing an object as the `$option` argument to `deflate_init()` and `inflate_init()` is now deprecated. Use `get_object_vars()` on the object instead. RFC: https://wiki.php.net/rfc/deprecations_php_8_6#passing_objects_for_options_parameter_of_deflate_init_and_inflate_init