PHP 8.2 brings type-system improvements for expressive and fine-grained type-safety, readonly classes, sensitive parameter redaction support, new random extension, and many new features along with several changes to streamline and modernize PHP language.

PHP 8.2 is a key milestone in PHP's journey in modernizing the PHP language. In addition to the exciting new features and improvements, PHP 8.2 streamlines the language by deprecating support for dynamic class properties, warnings when it encounters certain non-optimal INI configuration values, and fixing some of the legacy PHP behavior that affects how PHP sorts arrays and certain types of string transform/encode operations.


Type System Improvements

PHP 8.2 addresses several shortcomings and restrictions of PHP's type-system, allowing PHP applications to enjoy better type-safety. This includes adding support for true type, and allowing null and false types to be used as stand-alone types, and support for DNF types.

PHP 8.2 supports Disjoint Normal Form (DNF) types — It is now possible to combine Union Types (PHP 8.0) and Intersection Types (PHP 8.1), making it possible to declare precise and expressive parameter, return, and property types.

function process((HTMLRequest & RequestInterface) | APIRequest $request) {
  // ...
}

(HTMLRequest & RequestInterface) | APIRequest type declaration makes sure that the $request value is either an instance of APIRequest, or a class object that implements/extends/instance of both HTMLRequest and RequestInterface.


Support for true and false as stand-alone types makes it possible to replace bool type declarations if the boolean value is always the same.

function alwaysReturnsFalse(): false {}

function alwaysReturnsNull(): null {}

function alwaysReturnsTrue(): true {}

It was already possible to declare nullable types or a Union Type with null in older PHP versions. Since PHP 8.2, declaring null as a stand-alone type is allowed as well:

Learn in-depth



Readonly Classes

PHP 8.1 added support for readonly properties. A readonly property can only be set once, and PHP actively prevents the value from being modified even from within the scope of the class.

PHP 8.2 takes readonly properties a step further with readonly classes. When a class is declared as readonly, all of its properties are automatically declared readonly. Further, it prevents dynamic properties on readonly classes, and ensures that all properties are typed.

readonly class User {
    public string $username;
    public string $uid;
}

All properties of the readonly User class are automatically declared as readonly.


PHP 8.1 PHP 8.2

class User {
    public readonly int $uid;
    public readonly string $username;
}

readonly class User {
    public int $uid;
    public string $username;
}


New random extension

Over the history of PHP, it supported various Random Number Generators (RNG) with varying degrees of performance, use cases, and fit for secure applications. PHP 8.2 takes it a step further by refactoring all of the RNG-related functionality to a new extension named random.

The random extension provides the same functionality without breaking any APIs, so the existing rand, mt_rand, random_bytes, and random_int functions continue to work with no changes. It also provides a new OOP API to generate random numbers with a pluggable architecture, so it is now easy to mock the RNG and provide new RNGs, making PHP applications secure and easy to test.



Constants in Traits

In PHP 8.2, it is now possible to declare constants in traits. The traits cannot be accessed directly, but these constants become class constants when a class uses the trait.

trait FooBar {
    const FOO = 'foo';
    private const BAR = 'bar';
    final const BAZ = 'baz';
    final protected const QUX = 'qux';
}

class Test {
    use FooBar;
}

echo Test::BAZ; // 'bar'

This was not allowed in PHP 8.1 and older. Trait constants cannot be accessed directly (i.e. FooBar::FOO is not allowed). The trait constants must also not collide with other traits or the immediate class that uses them.



Sensitive Parameter Value Redaction Support

PHP 8.2 adds a new built-in parameter Attribute named #[\SensitiveParameter] that PHP makes sure to redact the actual value in stack traces and error messages.

Functions that accept passwords, private keys, or otherwise sensitive information can declare the parameters with the #[\SensitiveParameter] attribute. If the function calls within it causes a PHP error or an exception, the actual value passed to that parameter will be replaced with a \SensitiveparameterValue object.

PHP's built-in functions such as password_hash and password_verify are already declared with the #[\SensitiveParameter] attribute.

- function passwordHash(string $password)  {
+ function passwordHash(#[\SensitiveParameter] string $password)  {
        debug_print_backtrace();
  }

  passwordHash('hunter2');

With the #[\SensitiveParameter] attribute present, all stack traces actively redact the actual value passed to the parameter:

array(1) {
 [0]=> array(4) {
   ["file"]=> string(38) "..."
   ["line"]=> int(9)
   ["function"]=> string(3) "foo"
   ["args"]=> array(1) {
-     [0]=> string(38) "hunter2"
+     [0]=> object(SensitiveParameterValue)#1 (0) {}
   }
 }
}


New Functions and Classes

In addition to the major new features, PHP 8.2 also brings a set of new functions and classes:


Parse INI quantity values: ini_parse_quantity

ini_parse_quantity function parses any data size recognized by PHP INI values (such as 56K, 256M, or 1G) and returns the data size in bytes.

ini_parse_quantity('256M'); // 268435456

Maintain a Curl connection alive: curl_upkeep

curl_upkeep function in the PHP 8.2 Curl extension triggers the underlying Curl library to run necessary tasks to keep a Curl connection alive. The most common use case of this function is to keep an HTTP persistent connection (Keep-Alive) alive by periodically calling the curl_upkeep function.


Retrieve Cipher Key Length: openssl_cipher_key_length

In PHP 8.2 OpenSSL, there is a new function named openssl_cipher_key_length that returns the required length of the key (in bytes) for any supported OpenSSL cipher.

This function eliminates the need of hard-coding the required key's length for OpenSSL cipher operations.

openssl_cipher_key_length("CHACHA20-POLY1305"); // 32
openssl_cipher_key_length("AES-128-GCM"); // 16
openssl_cipher_key_length("AES-256-GCM"); // 32

Reset recorded peak memory usage: memory_reset_peak_usage

PHP 8.2 adds a new function named memory_reset_peak_usage that resets the peak memory usage returned by the memory_get_peak_usage function.

This can be helpful in applications that invoke or iterate an action multiple times, and need to record the peak memory usage of each invocation. Without the ability to reset the memory usage with the new memory_reset_peak_usage function, the memory_get_peak_usage returns the absolute peak memory usage throughout the entire run.



Deprecations in PHP 8.2

PHP 8.2 brings a fair share of deprecations as well. When a syntax, function, or a feature is deprecated, PHP emits a deprecation notice that should not disrupt or properly configured PHP applications, but gets logged to the error log.

Note that since PHP 8.0, PHP's default error reporting configuration is set to E_ALL.


Dynamic Properties Deprecated

One of the most notable deprecations in PHP 8.2 is that it deprecates class properties that are dynamically declared. There is an opt-out to it, but the recommended approach is to declare the class properties in the class declaration, preferably with a type declaration as well.

class User {
    public int $uid;
}

$user = new User();
$user->name = 'Foo';
Deprecated: Creation of dynamic property User::$name is deprecated in ... on

It is likely that many legacy PHP applications will be affected by this change, because legacy applications tend to not declare class properties when they are extended, or evolved over the years with changes.

The recommended fix is to declare the properties in the class:

class User {
    public int $uid;
+   public string $name; 
}

$user = new User();
$user->name = 'Foo';

There are opt-outs and exceptions to this deprecation too:


utf8_encode and utf8_decode Functions Deprecated

PHP 8.2 finally deprecates the utf8_encode and utf8_decode functions that were unfortunately named without noting that they only encode/decode from Latin 1 (ISO-8859-1).

Majority of the PHP applications that use these functions tend to not be aware of this shortcoming. The recommended replacements include the better functionality provided by mbstring, iconv, and intl extensions.


${var} String Interpolation Deprecated

PHP has always supported string variable interpolation with "foo {$bar}" pattern, and along with an alternative syntax that the dollar sign is placed outside the curly braces (e.g. "foo ${bar}").

In PHP 8.2, the alternative syntax of placing the dollar sign outside the curly braces is deprecated.

{.table-fixed}Deprecated in PHP 8.2 Recommended syntax for PHP 8.2
Hello ${name}; Hello {$name}
echo "Hello ${$var}"; echo "Hello {$$var}";

Additionally, PHP 8.2 also deprecates some of the partially-supported callable patterns and Mbstring extension's handling of Base64, Uuencode, QPrint, and HTML Entity encodings.


Installing/Upgrading to PHP 8.2

PHP 8.2 is now available to download/install in all regular sources:



Celebrate PHP 8.2 Release

Celebrate PHP 8.2 release with A3 size crisp posters available in both dark and light colors, with a name cloud of PHP 8.2 contributors!

{.table-fixed}PHP 8.2 Poster: Light
Download (5.1 MB MB)
PHP 8.2 Poster: Dark
Download (4.71 MB)

These posters can be printed on A3 landscape, optimized for 300 DPI prints.



Full List What's New and Changed in PHP 8.2

The full list of all new features, syntax and functionality changes, and deprecations with detailed examples are available at PHP 8.2 version page.

Recent Articles on PHP.Watch

All ArticlesFeed 
How to fix `mysql_native_password` not loaded errors on MySQL 8.4

How to fix mysql_native_password not loaded errors on MySQL 8.4

How to fix the SQLSTATE[HY000] [1524] Plugin 'mysql_native_password' is not loaded errors caused in MySQL 8.4 no longer enabling the mysql_native_password plugin by default.
How to fix PHP Curl HTTPS Certificate Authority issues on Windows

How to fix PHP Curl HTTPS Certificate Authority issues on Windows

On Windows, HTTPS requests made with the Curl extension can fail because Curl has no root certificate list to validate the server certificates. This article discusses the secure and effective solutions, and highlights bad advice that can leave PHP applications insecure.
AEGIS Encryption with PHP Sodium Extension

AEGIS Encryption with PHP Sodium Extension

The Sodium extension in PHP 8.4 now supports AEGIS-128L and AEGIS256 Authenticated Encryption ciphers. They are significantly faster than AES-GCM and CHACHA20-POLY1305. This article benchmarks them and explains how to securely encrypt and decrypt data using AEGIS-128L and AEGIS256 on PHP.
Subscribe to PHP.Watch newsletter for monthly updates

You will receive an email on last Wednesday of every month and on major PHP releases with new articles related to PHP, upcoming changes, new features and what's changing in the language. No marketing emails, no selling of your contacts, no click-tracking, and one-click instant unsubscribe from any email you receive.

Support PHP.Watch — If you find the articles, version information, Codex, and other PHP.Watch contributions useful, consider supporting through GitHub Sponsors. Your sponsorship helps dedicate more time to creating valuable content and improving the PHP community. Together, we can keep the momentum going — thank you for your support!

Thanks to the highest tier sponsor: @TomasVotruba for your generous support to keep PHP.Watch moving 💜