Skip to content
Accueil » New in PHP 8.1

New in PHP 8.1

The PHP team released its version 8.1 of the language on November 25, 2021. Version 8.0 had arrived with a bunch of new features. Let’s see together what the next version has in store for us.

The spread operator for arrays containing string keys

It was already possible to do this since 7.4, but only with digital keys. The reason was that PHP didn’t handle duplicates. Now it’s done. You can therefore proceed as follows:

$weekBegin = ['Tuesday' => 2, 'Wednesday' => 3];
$weekMiddle = ['Thursday' => 4, 'Friday' => 5];
$weekEnd = ['Saturday' => 6, 'Sunday' => 7];

$week = ['Monday' => 1, ...$weekBegin, ...$weekMiddle, ...$weekEnd];
Array
(
    "Monday" => 1
    "Tuesday" => 2
    "Wednesday" => 3
    "Thursday" => 4
    "Friday" => 5
    "Saturday" => 6
    "Sunday" => 7
)

Fibers

Fibers are functions that cannot be interrupted, and which can be used to implement cooperative multitasking. In short, it’s a piece of code that you can pause and resume later. The feature has been added in PHP, but is still in the testing and development phase. Here is what gives a simple use of a Fiber:

$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('Suspended value');
    echo "Value used to resume fiber: ", $value, "\n";
});

$value = $fiber->start();

echo "Value from fiber suspending: ", $value, "\n";

$fiber->resume('Hi again');
Value from fiber suspending: Suspended value
Value used to resume fiber: Hi again

Explicit octal notation

You can now write numeric values directly in bytes. This notation is done with the prefix 0o:

echo (0o16 === 16 ? 'true' : 'false') . "\n";
echo (0o16 === 14 ? 'true' : 'false') . "\n";
echo 0o7716_1414;
false
true
16573196

Final constants

The ability to declare final constants within a class is now possible. Very useful to prevent them from being overwritten by child classes:

ParentClass.php

class ParentClass
{
    final const IMMUTABLE = 'Try to change me';
}

ChildClass.php

require "ParentClass.php";

class ChildClass extends ParentClass
{
    public const IMMUTABLE = 'Okay, let me try';
}

index.php

require "ChildClass.php";

$child = new ChildClass();
Fatal error: ChildClass::IMMUTABLE cannot override final constant ParentClass::IMMUTABLE

The return type never

A function or method declared with type never indicates that it will not return a value and will throw an exception:

function neverReturn(): never
{
    return 'never';
}

echo neverReturn();
Fatal error: A never-returning function must not return

Intersecting types as Method Arguments

It was already possible in the methods to propose several types for an argument, with the symbol “|” :

function sumNumbers(int|float $numberOne, int|float $numberTwo)

You can now use the symbol “&” to require for a method argument the intersection of 2 types:

function iterate(Iterator&Countable $iterator)
{
    echo "This object contains " . $iterator->count() . " elements\n";
    foreach ($iterator as $item) {
        echo $item . "\n";
    }
}

$days = ['Monday', 'Tuesday'];

iterate(new ArrayIterator($days));
This object contains 2 elements
Monday
Tuesday

If the value sent does not match, an exception will be thrown:

Fatal error: Uncaught TypeError: iterate(): Argument #1 ($iterator) must be of type Iterator&Countable, array given

Support for “new” in constructors

Constructor objects can now be created directly via a “new”. It is also possible to do this on any initialization, for example in annotations:

use Assert\All;
use Assert\Length;
use Assert\NotNull;

final class TestClass
{
    private Generator $generator;

    #[All(
        new NotNull,
        new Length(min: 5))
    ]
    private string $name;

    public function __construct(Generator $generator)
    {
        $this->generator = new Generator();
    }
}

readonly property

Read-only properties cannot be changed after initialization, i.e. after they have been assigned a value:

TestClass.php

final class TestClass
{
    public readonly string $name;

    public function setName(string $name)
    {
        $this->name = $name;
    }
}

index.php

include "TestClass.php";

$test = new TestClass();

$test->setName('John');
$test->setName('Jack');

In the example above, the first call will work, because the name property has not yet been initialized. On the other hand, the second call will throw an exception:

Fatal error: Uncaught Error: Cannot modify readonly property TestClass::$name

Enum classes

PHP 8.1 comes with a specific class type to declare your enumeration constants. It happens as follows:

Days.php

enum Days
{
    case MONDAY;
    case TUESDAY;
    case WEDNESDAY;
    case THURSDAY;
    case FRIDAY;
    case SATURDAY;
    case SUNDAY;
}

index.php

include "Days.php";

echo 'First day of week = ' . Days::MONDAY->name;

print_r(Days::cases());
First day of week = MONDAY
Array
(
    [0] => Days Enum([name] => MONDAY)
    [1] => Days Enum([name] => TUESDAY)
    [2] => Days Enum([name] => WEDNESDAY)
    [3] => Days Enum([name] => THURSDAY)
    [4] => Days Enum([name] => FRIDAY)
    [5] => Days Enum([name] => SATURDAY)
    [6] => Days Enum([name] => SUNDAY)
)

Conclusion

There you go, you know everything about PHP version 8.1. To your keyboards to take control of all these new features! 😇

Leave a Reply

Your email address will not be published. Required fields are marked *