Go to content
The Codest
  • About Us
  • Services
  • Our Team
  • Case studies
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
  • About Us
  • Services
  • Our Team
  • Case studies
    • Blog
    • Meetups
    • Webinars
    • Resources
Careers Get in touch
2022-08-31
Software Development

PHP 8.2: What's new?

Sebastian Luczak

PHP Unit Leader

PHP 8.2: What's new? - Image

The new version of PHP is just around the corner. What are the new implementations you should know about? Check this article to find out!

PHP 8.2 is about to be released. Perhaps it will be the version that makes an upgrade into PHP 8 seem appealing to everyone. Let’s talk about what developers can look forward to with PHP 8.2 and prepare for its latest version. But first, let’s quickly go through all the PHP versions and changes over the years.

Overview of past versions

PHP 7.4

Typed properties

<?php
class User {
    public int $id;
    public string $name;
}
?>

Arrow functions

<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);
?>

Limited return type covariance and argument type contravariance

<?php
class A {}
class B extends A {}

class Producer {
    public function method(): A {}
}
class ChildProducer extends Producer {
    public function method(): B {}
}
?>

Null coalescing assignment operator

<?php
$array['key'] ??= computeDefault();
// is roughly equivalent to
if (!isset($array['key'])) {
    $array['key'] = computeDefault();
}
?>

Unpacking inside arrays

<?php
$parts = ['apple', 'pear'];
$fruits = ['banana', 'orange', ...$parts, 'watermelon'];
// ['banana', 'orange', 'apple', 'pear', 'watermelon'];
?>

Custom object serialization

<?php
// Returns array containing all the necessary state of the object.
public function __serialize(): array;

// Restores the object state from the given data array.
public function __unserialize(array $data): void;
?>

PHP 8.0

Released in November 2020, PHP 8.0 brought us the best features yet, which includes:

Named arguments

htmlspecialchars($string, double_encode: false);

Attributes

class PostsController
{
    #[Route("/api/posts/{id}", methods: ["GET"])]
    public function get($id) { /* ... */ }
}

Constructor property promotion

class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}

Union types

class Number {
  public function __construct(
    private int|float $number
  ) {}
}

new Number('NaN'); // TypeError

Match expression

echo match (8.0) {
  '8.0' => "Oh no!",
  8.0 => "This is what I expected",
};
//> This is what I expected

Nullsafe operator

$country = $session?->user?->getAddress()?->country;

PHP 8.1

Enumerations

enum Status
{
    case Draft;
    case Published;
    case Archived;
}
function acceptStatus(Status $status) {...}

Readonly Properties

class BlogData
{
    public readonly Status $status;
  
    public function __construct(Status $status)
    {
        $this->status = $status;
    }
}

First-class Callable Syntax

$foo = $this->foo(...);

$fn = strlen(...);

New in initializers

class Service
{
    private Logger $logger;
   
    public function __construct(
        Logger $logger = new NullLogger(),
    ) {
        $this->logger = $logger;
    }
}

Pure Intersection Types

function count_and_iterate(Iterator&Countable $value) {
    foreach ($value as $val) {
        echo $val;
    }

    count($value);
}

Fibers

$response = $httpClient->request('https://example.com/');
print json_decode($response->getBody()->buffer())['code'];

PHP 8.2

PHP 8.2 introduces further changes aimed at making the developer's life easier and optimizing his work even more. Below is the list of new features.

Readonly classes

One of the biggest improvements in the new version of PHP is the ability to directly create a readonly class. A class described with this feature will automatically propagate it for its variables. DTO classes will now look neat and clean!

readonly class InvoiceDTO
{
    public function __construct(
        public UUID $uuid, 
        public Issuer $issuer,
        public DateTime $issuedAt,
    ) {}
}

Deprecate dynamic properties

The second huge change is the deprecation of dynamic variables in classes. The following implementation will throw a deprecation in PHP 8.2 and ErrorException in future version of PHP.

class MyUser
{
    public string $name;
}
(...)
$myUser->name = 'Name'; // OK
$myUser->surname = 'Surname'; // deprecated / errorexception

It is worth mentioning that classes implementing __get and __set methods and classes directly inheriting from stdClass can still implement magic methods without any obstacles.

Here I also refer you to an interesting thread on GitHub, where PHP-CS developers discuss this change and the need to modify their popular tool for the new version of the language.

Last but not least, you can disable this behavior via Annotation.

#[AllowDynamicProperties]
class MyUser
{
    public string $name;
}

$myUser->surname = 'Surname'; // OK

New standalone types: null, true, and false

Until now, functions that always returned a true or false value had to be described with a bool type.

function alwaysTrue(): bool { return true; }

From now on, we can use true and false as simple types in the returned values of functions.

function alwaysTrue(): true { return true; }

Disjunctive Normal Form Types

(DNF) is a standard way of organizing boolean expressions. Specifically, it means structuring a boolean expression into an ORed series of ANDs. When applied to type declarations, it allows for a standard way to write combined Union and Intersection types that the parser can handle.

It's a big change, as we now can have nullable intersection types, for example:

function getFullName((HasName&HasSurname)|null $user) { ... }

Constants in Traits

I'm not a big proponent of using Traits and such a change is purely cosmetic to me, especially since it doesn't allow you to use Trait values without initializing the object.

trait Foo {
    public const FLAG_1 = 1;
    protected const FLAG_2 = 2;
    private const FLAG_3 = 2;
 
    public function doFoo(int $flags): void {
        if ($flags & self::FLAG_1) {
            echo 'Got flag 1';
        }
        if ($flags & self::FLAG_2) {
            echo 'Got flag 2';
        }
        if ($flags & self::FLAG_3) {
            echo 'Got flag 3';
        }
    }
}

Redacting parameters in back traces

One of the most important changes I am looking forward to. In the latest version of PHP we will be able to mark variables as SensitiveParameterValue. Why should we?

PHP's stack traces in exceptions are very useful for debugging, however, they allow you to preview parameter values. For example, let's imagine PDO code used to connect to a database. The debug trace would look as follows:

PDOException: SQLSTATE[HY000] [2002] No such file or directory in /var/www/html/test.php:3
Stack trace:
#0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password')
#1 {main}

After using Annotation #[SensitiveParameter] our stack trace will no longer show the value of the variable.

function test(
    $foo,
    #[\SensitiveParameter] $bar,
    $baz
) {
    throw new \Exception('Error');
}
 
test('foo', 'bar', 'baz');
 
/*
Fatal error: Uncaught Exception: Error in test.php:8
Stack trace:
#0 test.php(11): test('foo', Object(SensitiveParameterValue), 'baz')
#1 {main}
  thrown in test.php on line 8
*/

Fetch properties of enums in const expressions

As author says , the primary motivation for this change is to allow fetching the name and value properties in places where enum objects aren't allowed, like array keys. We could work on arrays so they could be extended to allow enums or all objects as keys, but allowing to fetch properties of enums is simpler.

enum A: string {
    case B = 'B';
    const C = [self::B->value => self::B];
}

Date functions return types

Previously static methods worked like this:

DateTime::createFromImmutable(): DateTime
DateTimeImmutable::createFromMutable(): DateTimeImmutable

In PHP 8.2 it's going to be changed to:

DateTime::createFromImmutable(): static
DateTimeImmutable::createFromMutable(): static

This is a breaking change for library creators and/or all custom implementations of DateTime.

Deprecate and Remove `utf8_encode` and `utf8_decode`

Those were two function that did not served it purpose, as they only converted between ISO-8859-1 and UTF-8. PHP Manual suggest using mb_convert_encoding instead.

Locale-independent case conversion

Locale sensitivity is best described by author of the RFC:

Prior to PHP 8.0, PHP's locale was set from the environment. When a user installs Linux, it asks what language you want it to be in. The user might not fully appreciate the consequences of this decision. It not only sets the user interface language for built-in commands, it also pervasively changes how string handling in the C library works. For example, a user selecting “Turkish” when installing Linux would find that applications calling toupper('i') would obtain the dotted capital I (U+0130, “İ”).

In an era of standardized text-based protocols, natural language is a minority application for case conversion. But even if the user did want natural language case conversion, they would be unlikely to achieve success with strtolower(). This is because it processes the string one byte at a time, feeding each byte to the C library's tolower(). If the input is UTF-8, by far the most popular modern choice, strtolower() will mangle the string, typically producing invalid UTF-8 as output.

PHP 8.0 stopped respecting the locale environment variables. So the locale is always “C” unless the user explicitly calls setlocale(). This means that the bulk of the backwards-incompatible change is already behind us. Any applications depending on the system locale to do case conversion of legacy 8-bit character sets would have been broken by PHP 8.0.

What it means is that all of below function will do ASCII case conversion from PHP.8.2: strtolower, strtoupper, stristr, stripos, strripos, lcfirst, ucfirst, ucwords, str_ireplace

Deprecate ${} string interpolation

We've got a lot of ways of embedding variables into strings in PHP:

  • Directly embedding variables (“$foo”)
  • Braces outside the variable (“{$foo}”)
  • Braces after the dollar sign (“${foo}”)
  • Variable variables (“${expr}”, equivalent to (string) ${expr})

To avoid confusion and misuse those will not work anymore:

"Hello ${world}";
Deprecated: Using ${} in strings is deprecated

"Hello ${(world)}";
Deprecated: Using ${} (variable variables) in strings is deprecated

Summary

These are not all the changes that PHP 8.2 will offer us. Unfortunately, we still didn't get support for generic types, according to what Nikita said the monomorphized generics would add too much performance overhead, and reified generics require many changes across the whole codebase. What is noticeable, however, is the discipline and vision of the product. The changes introduced in successive versions of the language are becoming clearer, and those interested will notice that PHP is moving in the right direction both in the area of syntax simplification and support for novelties. I expect that as early as next year we will see callable as a valid type.

cooperation banner

Related articles

Software Development

4 Common Web Accessibility Issues to Know

The web is used by millions of different people everyday, one of our main goals as developers is to make the web accessible for everyone. This article will introduce some common web accessibility issues and ways to solve them.

Reda Salmi
Software Development

What You Shroud Know about PHP Development?

This article is devoted to enriching your PHP business knowledge. Find out where to find PHP developers, what are the pros and cons of this language and many more.

Sebastian Luczak
Software Development

PHP Development. Symfony Console Component - Tips & Tricks

This article was created with the aim to show you the most useful and retrieving tips and tricks about Symfony Console Development.

Sebastian Luczak
Startups

The Right Way to Find Top Java Developers

Finding the perfect Java developer can be a daunting task. As the market demand for such professionals grows at an astonishing pace, available sources for talent search can sometimes seem limited.

Grzegorz Rozmus

Subscribe to our knowledge base and stay up to date on the expertise from industry.

About us

Tech company specializing in scaling tech teams for clients and partners thanks to top-class development engineers.

    United Kingdom - Headquarters

  • Office 303B, 182-184 High Street North E6 2JA London, England

    Poland - Local Tech Hubs

  • Business Link High5ive, Pawia 9, 31-154 Kraków, Poland
  • Brain Embassy, Konstruktorska 11, 02-673 Warsaw, Poland
  • Aleja Grunwaldzka 472B, 80-309 Gdańsk, Poland

    The Codest

  • Home
  • About us
  • Services
  • Case studies
  • Know how
  • Careers

    Services

  • PHP development
  • Java development
  • Python development
  • Ruby on Rails development
  • React Developers
  • Vue Developers
  • TypeScript Developers
  • DevOps
  • QA Engineers

    Resources

  • What are top CTOs and CIOs Challenges? [2022 updated]
  • Facts and Myths about Cooperating with External Software Development Partner
  • From the USA to Europe: Why do American startups decide to relocate to Europe
  • Privacy policy
  • Website terms of use

Copyright © 2022 by The Codest. All rights reserved.

We use cookies on the site for marketing, analytical and statistical purposes. By continuing to use, without changing your privacy settings, our site, you consent to the storage of cookies in your browser. You can always change the cookie settings in your browser. You can find more information in our Privacy Policy.