PHP 8.2: Major Features

Field notes for teams moving from PHP 8.1.x to 8.2.x: language additions, security-oriented attributes, stricter string handling, and the deprecations you should clear before the next jump.

Table of Contents


PHP 8.2 keeps the language moving toward explicitness: readonly classes, finer-grained type expressions (including DNF), and #[SensitiveParameter] so secrets do not leak through stack traces. It also tightens several “sharp edges” (locale-free ASCII case folding for core string helpers, str_split(''), glob() under open_basedir) and deprecates patterns—especially dynamic properties—that hide bugs until runtime.

#[SensitiveParameter] and safer stack traces

The #[\SensitiveParameter] attribute marks parameters that must be redacted in stack traces and debugging output, reducing accidental credential leakage in logs and error pages.

function connect(#[\SensitiveParameter] string $password): void
{
    throw new RuntimeException('fail');
}

Pair this with disciplined logging and never echo raw exceptions in production.

Practical recipe: mark secrets at the boundary

Use #[\SensitiveParameter] on parameters that might end up in exceptions (client wrappers, auth helpers). It keeps stack traces useful without leaking credentials.

final class ApiClient
{
    public function __construct(
        private readonly string $baseUrl,
        #[\SensitiveParameter] private readonly string $token,
    ) {}
}

Readonly classes

A class can be declared readonly, making all its instance properties readonly and requiring initialization at construction time (similar to applying readonly to every property).

readonly class Point
{
    public function __construct(
        public int $x,
        public int $y,
    ) {}
}

Use this for immutable value objects and DTOs where the whole object graph should be frozen after construction.

Standalone types (null, false, true) and DNF

PHP 8.2 allows null, false, and true as stand-alone types in declarations (not only as union members in older forms).

DNF (Disjunctive Normal Form) types let you combine union and intersection types in a normalized shape, e.g. (A&B)|null—useful for precise APIs without losing nullability.

function accepts((Countable&Traversable)|null $c): void {}

Constants in traits & enums in constant expressions

  • Constants in traits are now allowed—helpful for shared configuration without an extra base class.
  • Enum properties in constant expressions: you can reference enum cases/properties where constant expressions are required, enabling richer compile-time configuration.

INI: error_log_mode

The error_log_mode INI directive sets the file permissions for the error log file when PHP creates it—useful for hardened deployments (e.g. avoiding world-readable logs).

Random extension

The Random extension consolidates and extends random-number generation APIs, with clearer RNG choices and fewer foot-guns than ad hoc use of older functions alone. Prefer it for new code that needs reproducible seeds, better algorithms, or testability.

Practical recipe: Randomizer for tokens and sampling

$engine = new Random\Engine\Mt19937(random_int());
$randomizer = new Random\Randomizer($engine);
$token = $randomizer->getBytesFromString('0123456789abcdef', 32);

Use a seeded engine in tests to make random output deterministic; use a cryptographically safe engine when generating secrets (see the extension docs for Random\Engine choices).

Notable extension updates (cURL, PCRE)

  • cURL: CURLINFO_EFFECTIVE_METHOD exposes the effective HTTP method; curl_upkeep() helps with connection upkeep; newer libcurl constants are exposed where available.
  • PCRE: the n (NO_AUTO_CAPTURE) modifier makes ordinary () groups non-capturing unless named—handy for complex patterns with fewer numbered backreferences.

Backward incompatible changes (migration notes)

Date & time

  • DateTime::createFromImmutable() / DateTimeImmutable::createFromMutable() now use tentative static return types (narrower than before for inheritance tooling).
  • Relative date formats: number symbols no longer allow multiple signs (e.g. +-2).

Standard library (high impact)

  • Locale-insensitive ASCII case: strtolower(), strtoupper(), stri*, str_ireplace(), lcfirst(), ucfirst(), ucwords(), and related calls are no longer locale-sensitive; they behave like the "C" locale. Use mbstring for localized case mapping.
  • str_split('') now returns [] (previously [""]).
  • glob() / GlobIterator: under open_basedir, empty array vs false behavior and warnings changed—audit directory scanning in restricted hosting.
  • FilesystemIterator: SKIP_DOTS is no longer forced; set flags explicitly if you relied on the old default.
  • ksort / krsort: SORT_REGULAR uses PHP 8 numeric string rules consistently.
  • var_export(): leading backslashes for class names are no longer omitted (fully qualified names).

ODBC / PDO_ODBC

Username and password are escaped when appended to connection strings—fixes injection/malformed strings; verify integration tests against real DSNs.

SPL

Several SplFileObject methods now enforce signatures; return types for some methods were tightened (hasChildren, getChildren).

Note: Some deployments observed date_default_timezone_get() falling back to UTC when neither date_default_timezone_set() nor date.timezone is set—validate timezone assumptions on upgrade.

Deprecations (fix before they become errors)

Dynamic properties

Creating dynamic properties on arbitrary classes is deprecated unless the class uses #[\AllowDynamicProperties] (or extends types like stdClass that allow it). Prefer declared properties, WeakMap for external metadata, or explicit __get/__set.

Partial callables

Callables only accepted by call_user_func() but not by $callable() form—e.g. "self::method", "parent::method", certain array forms—are deprecated. Normalize to Foo::bar or [Class::class, 'method'] patterns.

String interpolation

"${var}" / "${expr}" style interpolation is deprecated; use "{$var}" or explicit concatenation.

Other

  • utf8_encode / utf8_decode: deprecated (use mb_convert_encoding or iconv).

Extensions & runtime notes

  • OpenSSL: AEAD support for chacha20-poly1305 where available.
  • OCI8: prefetch tuning for LOBs via INI and oci_set_prefetch_lob() on supported Oracle versions.
  • DBA (LMDB): flags for subdirectory behavior when creating DB files.

Closing thoughts

PHP 8.2 rewards teams that model data explicitly: readonly classes, richer types, fewer accidental leaks via #[SensitiveParameter], and deprecations that push legacy patterns toward declared properties and modern callables. Budget time for string/locale and timezone checks—these upgrades are often silent until they hit production traffic.