# Deprecated Features

## PHP Core

### Using "namespace" as a class constant name

Declaring a [class constant](#language.oop5.constants) named `namespace` is now deprecated. `namespace` is a semi-reserved keyword, and the name is being reserved for possible future syntax such as a `::namespace` pseudo-constant analogous to `::class`. Methods and static properties named `namespace` are not affected. Rename the constant, for example to `NAMESPACE_NAME`.

### Returning from a finally block

Using the `return` statement inside a ENTITY block is now deprecated, and emits a compile-time deprecation notice. Such a `return` silently discards an exception thrown by, or overwrites the value returned from, the associated `try` or `catch` block, so failures vanish without a trace. Move the `return` out of the `finally` block instead; the same result can always be expressed without it.

<div class="informalexample">

```
<?php
function getConfig(): array
{
    try {
        return loadConfig(); // throws if the file is missing
    } finally {
        return []; // Deprecated: the exception is gone, the caller just gets []
    }
}

    
```

</div>

### Nullable return type for \_\_debugInfo()

Declaring a return type of `arraynull` for [\_\_debugInfo()](#language.oop5.magic.debuginfo) is now deprecated. Returning ENTITY from this method was [already deprecated in PHP 8.5](#migration85.deprecated.core.return-null-from-debuginfo), so the nullable return type no longer describes valid behaviour. Declare `array` instead.

### Returning values from \_\_construct() and \_\_destruct()

Returning a value from [\_\_construct()](#language.oop5.decon.constructor) or [\_\_destruct()](#language.oop5.decon.destructor) is now deprecated, and emits a compile-time deprecation notice. These methods cannot declare a return type, and their return value can never be observed during normal use, which made returning a value confusing at best. Using `return;` without a value to skip the remaining logic is still allowed, as is calling these methods manually.

For the same reason, using `yield` to make [\_\_construct()](#language.oop5.decon.constructor) or [\_\_destruct()](#language.oop5.decon.destructor) a [generator](#language.generators) is now deprecated.

### Naming a function readonly

Declaring a function named `readonly` is now deprecated. [readonly](#language.oop5.properties.readonly-properties) is a reserved keyword; a lexer exception was added in PHP 8.1 solely to keep an existing WordPress function of that name working, and no other keyword in PHP receives such special treatment. Rename the function.

### Using let, is, or \_ as an identifier

Using `let` or `is` as the name of a class, interface, trait, enum, function, or constant (including via `define`) is now deprecated, as is using either as the alias in a `class_alias` call or in a `use`, `use function`, or `use const` declaration. The names are being reserved as keywords for potential future features: `let` for block scoping and `is` for pattern matching. Rename the affected symbols.

The [deprecation of `_` as a class name in PHP 8.4](#migration84.deprecated.core.underscore-class-name) is extended to constants: declaring a constant named `_` with `const` or `define`, and aliasing a class or constant to `_` in a `use` declaration, are now deprecated. Functions named `_`, including the `_` alias of `gettext`, are not affected.

### Third argument to define()

Passing the `case_insensitive` argument to `define` is now deprecated. Case-insensitive constants were removed in PHP 8.0, since when the argument has been ignored. Explicitly passing ENTITY now emits a deprecation notice. Passing ENTITY continues to emit a warning, whose message now states that this will become an error in PHP 9.0. Omit the argument.

### is_a() and is_subclass_of() with a string when allow_string is false

Calling `is_a` or `is_subclass_of` with a string as the first argument while `allow_string` is ENTITY is now deprecated. In that case the functions always return ENTITY, even when the class is already loaded, so such a call indicates a bug. To avoid triggering autoloading, check `class_exists` with autoloading disabled first, and then call the function with `allow_string` set to ENTITY.

### metaphone()

The `metaphone` function is now deprecated. It implements the original 1990 Metaphone algorithm, which is limited to English pronunciation rules and has long been superseded by Double Metaphone and Metaphone 3. Phonetic algorithms are language-specific and frequently updated, so they are better served by a userland library; use one instead.

### More than 16 filters in a php://filter URL

Using more than 16 filters in a [php://filter](#wrappers.php) URL without configuring the `filter.max_filter_count` stream context option now emits a deprecation notice. Long filter chains have no known legitimate use, but are the basis of a class of attacks that turn a local file inclusion or an arbitrary file read into remote code execution. When `filter.max_filter_count` is set explicitly, exceeding it is already an error: opening the stream fails with a warning.

Code that needs more filters should either add them with `stream_filter_append` or `stream_filter_prepend`, which are not limited, or raise the limit through the context option, for example globally with `stream_context_set_default`.

### Passing objects to array_walk(), array_walk_recursive(), and http_build_query()

Passing an object as the `array` argument to `array_walk` or `array_walk_recursive` is now deprecated. A small number of functions silently interpret an object as the array of its visible properties. Modifying such properties through a by-reference callback violates [readonly](#language.oop5.properties.readonly-properties) semantics and can corrupt enum cases, and `array_walk_recursive` does not recurse into nested objects anyway. Call `get_object_vars` on the object first and pass the resulting array.

Passing an object as the `data` argument to `http_build_query` is now deprecated. Objects encountered as values within `data` now also emit a deprecation notice when they are interpreted as arrays. Treating objects as arrays has been a recurring source of confusion, in particular for Stringable objects, which users expect to be converted to a string instead. Convert objects to arrays with `get_object_vars`, recursively if necessary, before calling the function.

### is_double(), is_long(), is_integer(), and doubleval()

Following the [deprecation of the non-canonical cast names in PHP 8.5](#migration85.deprecated.core.non-canonical-cast-names), the function aliases that carry the same outdated type names are now deprecated. They behave identically to their canonical counterparts, which should be used instead: `is_double` =\> `is_float`, `is_long` =\> `is_int`, `is_integer` =\> `is_int`, `doubleval` =\> `floatval`

### strcoll() and SORT_LOCALE_STRING

The `strcoll` function is now deprecated. It compares strings according to the `LC_COLLATE` setting of the current locale, which is global process state set via `setlocale` that any library can change, it is not binary safe unlike every other string comparison function, and some locales do not implement correct collation rules. Use Collator::compare from the [intl](#book.intl) extension instead, which is accurate and has up-to-date collation rules.

The `SORT_LOCALE_STRING` flag of the sort functions is now deprecated for the same reasons, as it sorts using `strcoll`. Use one of the following methods of the `Collator` class instead: Collator::sort, Collator::asort, Collator::sortWithSortKeys

## Bzip2

Passing an object as the parameters of the [bzip2.compress and bzip2.decompress](#filters.compression) stream filters is now deprecated, as only an associative array is documented and supported. Call `get_object_vars` on the object first and pass the resulting array.

## GMP

The shift (`ENTITYENTITY`, `ENTITYENTITY`) and exponentiation (`**`) operators on `GMP` objects now emit a deprecation notice when the right operand is a `float` whose conversion to `int` loses precision, consistent with the deprecation of implicit lossy float to int conversions elsewhere in the language.

## MBString

The mbregex functions have been deprecated, because the underlying Oniguruma library is no longer maintained; its maintenance ended in April 2025. The functions will be removed in PHP 9.0. For most use cases the [PCRE](#book.pcre) functions with the `u` modifier are a suitable replacement. The affected functions are: `mb_ereg`, `mb_ereg_match`, `mb_ereg_replace`, `mb_ereg_replace_callback`, `mb_ereg_search`, `mb_ereg_search_getpos`, `mb_ereg_search_getregs`, `mb_ereg_search_init`, `mb_ereg_search_pos`, `mb_ereg_search_regs`, `mb_ereg_search_setpos`, `mb_eregi`, `mb_eregi_replace`, `mb_regex_encoding`, `mb_regex_set_options`, `mb_split`

The `MB_ONIGURUMA_VERSION` constant and the [mbstring.regex_retry_limit](#ini.mbstring.regex-retry-limit) and [mbstring.regex_stack_limit](#ini.mbstring.regex-stack-limit) INI directives are deprecated along with them.

Passing an object as the `vars` argument to `mb_convert_variables` is now deprecated, as objects are silently interpreted as the array of their visible properties. Call `get_object_vars` on the object first, or use `mb_convert_encoding`, which converts arrays recursively and returns the result instead of modifying its argument in place.

## MySQLi

The `mysqli_get_charset` function and the mysqli::get_charset method are now deprecated, without replacement. They expose internal implementation details of the character set that have been meaningless since the switch to mysqlnd; in particular the reported collation does not correspond to the collation defined by the server. To get the name of the current character set, use `mysqli_character_set_name` or mysqli::character_set_name.

The `mysqli_stmt_init` function and the mysqli::stmt_init method are now deprecated. They create an empty statement object that still has to be prepared before use, and are a source of statement objects left in an inconsistent state. Use `mysqli_prepare` or mysqli::prepare instead, which prepare the statement in one step. For the same reason, calling the mysqli_stmt::\_\_construct constructor without the `query` parameter is now deprecated; pass the query to the constructor instead.

## Reflection

Calling ReflectionProperty::setValue or ReflectionProperty::setRawValue with an object that is not an instance of the class on which the property was declared is now deprecated. Unlike the other `ReflectionProperty` methods, which throw for such objects, these methods silently set a property on the unrelated object, which is no better than a normal assignment and conceptually wrong.

Passing an object to ReflectionMethod::invoke or ReflectionMethod::invokeArgs when invoking a static method is now deprecated. Static methods have no `$this`, so the object was ignored entirely and never validated. Pass ENTITY instead.

## Session

Passing an object that does not implement both the SessionIdInterface::create_sid and SessionUpdateTimestampHandlerInterface::validateId methods to `session_set_save_handler` is now deprecated, regardless of which interfaces the object declares. These methods are required for a save handler to behave correctly under [session.use_strict_mode](#ini.session.use-strict-mode), which is [enabled by default as of PHP 8.6](#migration86.incompatible.session) and mitigates session fixation.

Accordingly, a deprecation notice is now emitted when a class implements SessionHandlerInterface without defining the SessionIdInterface::create_sid or SessionUpdateTimestampHandlerInterface::validateId methods. In PHP 9.0 these methods will be moved from SessionIdInterface and SessionUpdateTimestampHandlerInterface into SessionHandlerInterface, where they will be required. Implement both methods on custom save handlers now.

## SPL

The `spl_classes` function is now deprecated. No other extension exposes such a function, and the Reflection extension is always available. Use ReflectionExtension::getClassNames instead.

The `spl_object_hash` function is now deprecated. Since PHP 8.1 its return value has been nothing more than a reformatted `spl_object_id`, and the name is misleading as the value is not derived from the contents of the object. The string form is also error-prone: two hashes can compare loosely equal because both are numeric strings. Use `spl_object_id` instead.

The following `ArrayIterator` methods are now deprecated. They only exist because `ArrayIterator` historically shared its implementation with `ArrayObject`; most of them make little sense on an iterator and prevent optimizing its implementation. The corresponding `ArrayObject` methods are not deprecated. ArrayIterator::getFlags, ArrayIterator::setFlags, ArrayIterator::asort, ArrayIterator::ksort, ArrayIterator::uasort, ArrayIterator::uksort, ArrayIterator::natsort, ArrayIterator::natcasesort, ArrayIterator::unserialize, ArrayIterator::serialize

The CSV methods of `SplFileObject` are now deprecated. Their historical design inconsistencies, further exposed by named arguments, have made them increasingly difficult to maintain, and CSV handling does not naturally belong in `SplFileObject`. Use `fgetcsv` and `fputcsv` on a stream instead. SplFileObject::fgetcsv, SplFileObject::fputcsv, SplFileObject::setCsvControl, SplFileObject::getCsvControl

## Zlib

Passing an object as the parameters of the [zlib.deflate and zlib.inflate](#filters.compression) stream filters is now deprecated, as only an associative array is documented and supported. Call `get_object_vars` on the object first and pass the resulting array.

Passing an object as the `options` argument to `deflate_init` or `inflate_init` is now deprecated, as objects are silently interpreted as the array of their visible properties. Call `get_object_vars` on the object first and pass the resulting array.