Code Published on the 9th December 2021

What's new in PHP 8.1, features and improvements

La version PHP 8.1 est sortie le 25 novembre 2021. Profitons-en pour faire un tour d’horizon des principales nouveautés au programme de cette version.

What's new in PHP 8.1, features and improvements

On November, 25th, the PHP Core team announced the release of PHP version 8.1. Let's take a moment to go through some of its new features.

We are only going to focus on some major new features. Each release also brings its share of deprecations, breaking changes and minor changes but this is beyond the scope of this article. If you're interested, you can go through every change on the official migration guide.

Pure Intersection Types

Support for intersection types is coming, following support for union types introduced in PHP 8.0, with an opposite usage.

Where union types (declared with the | (OR) operator) specify that a parameter must be one of the specified types, intersection types (declared with the & (AND) operator) require the parameter to be of all the specified types.

// Union type

public function foo(Foo|Bar $input); // $input must either be Foo **or** Bar

// Intersection type

public function foo(Foo&Bar $input); // $input must be Foo **and** Bar

You can learn more about intersection types on the official page.

Never return type

never return type indicates that a method will stop the program flow, either by throwing an exception or by explicitly calling exit.

function dumpAndDie($value) : never {
	var_dump($value);
	exit() ;
}

Documentation about this feature can be read here.

Enums

Many languages already support them and PHP is finally adding support for enums in version 8.1.

Quick reminder: an enum (aka enumeration) is a set of named values.

Let's take the example of a deck of cards. The suits of the cards can be defined in an enum

enum Suit {
    case CLUBS;
    case DIAMONDS;
    case HEARTS;
    case SPADES;
}

Imagine now a Card object which must be initialized with a Suit parameter. Our enum will allow us to set the type of the intended parameter.

class Card
{
	public function __construct(Suit $suit){// code};
}

$card = new Card(Suit::CLUBS);

Enums in PHP comes with powerful features. Let us walk you through some of them :

  • much like classes, enums may contain method. It's also possible for them to have static methods.
// Enumeration and method

enum Suit {
    case CLUBS;
    case DIAMONDS;
    case HEARTS;
    case SPADES;

		public function getColor(): string
		{
			return match($this)
			{
				self::CLUBS => 'black',
				self::DIAMONDS => 'red',
				self::HEARTS => 'red',
				self::SPADES => 'black',
			};
		}
}

// Here is how to use this method
$suit = Suit::SPADES;
$suit->getColor(); // 'black'
  • much like classes, enums can implement interfaces.
  • it is possible to assign a specific value for each of the enum case. Those values can only be of type int or string. In that case the enumeration is called a Backed enum.
enum Suit: string {
    case CLUBS = '♣️';
    case DIAMONDS = '♦️';
    case HEARTS = '♥︎';
    case SPADES = '♠️';
}

// get the associated value
$value = Suit::DIAMONDS->value; // '♦️', value  is a readonly public property
// restoring from a value
$suit = Suit::from('♠️'); // Suit::SPADES

For a complete overview of all the features enum come with, have a look at the official RFC page.

Fibers

Fibers (aka 'green threads' aka 'coroutines') is a new feature in PHP to handle parallelism. A Fiber is a code block that maintains its own stack (variables and state) and that can be started, suspended, resumed or terminated by the main thread or the Fiber itself.

This feature is probably not something you'll want to use every day but you can find detailed specifications of the official RFC page.

Performance improvements

Not really a new feature but the PHP core team brought some performance gain to opcache under the name "inheritance cache". This allows to cache links between classes. A performance gain between 5% and 8% has been reported thanks to this change.

More details about this change can be found on the GitHub page of the pull request.

Array unpacking with string keys

Array unpacking has existed in PHP since version 7.4 but only numeric keys were supported. Coming in version 8.1, it will now be possible to use array unpacking with string keys. Rules to manage duplicated keys will follow those of array_merge, meaning that later string keys overwrite earlier ones.

$array1 = ["key1" => 1];
$array2 = ["key2" => 2];
$array = ["key1" => 0, ...$array1,...$array2];

var_dump($array); // ["key1" => 1, "key2" => 2]

Link to this RFC.

new keyword in initializers

Usage of the new keyword has been extended. You can find all the expressions that are now allowed in the code below.

// static variable initializer
static $x = new Foo;
 
// global constant initializer
const C = new Foo;

// parameter default values
function test($param = new Foo) {}
 
// attribute arguments
#[Attr(new Foo)]
class Test {
    public function __construct(
        public $prop = new Foo,
    ) {}
}

Readonly properties

Classes properties can now be declared as readonly, thus preventing a modification of the property after initialization.

class Person {
	public function __construct(
		public readonly $name
	) {}
}

$person = new Person('John');
$person->name = 'Jack' // this will result in an Error
// Error: Cannot modify readonly property Person::$name

Everything you need to know about this in the corresponding RFC.

First-class callable syntax

With PHP 8.1 it is now possible to make a closure from a callable by calling that callable with ... as its argument.

Since a code block is worth a thousand words:

// our callable
function add($a,$b){return $a + $b;}

// here we make the closure
$fn = add(...)

// this is how we use it
echo $fn(a: 3, b: 4) // 7

As usual the link to the RFC.

New method array_is_list

This new helper method checks if an array's keys are numerical, in ascending order, starting from index 0.

$list = [1 => 'a', 0 => 'b'];
array_is_list($list); // false because keys are not ordered

$list = [0 => 'a', 1 => 'b'];
array_is_list($list); // true because the 3 conditions are met

$list = ['a', 'b'];
array_is_list($list); // true because the 3 conditions are met

$list = [1 => 'a', 2 => 'b', 3 => 'c'];
array_is_list($list); // false because 1st index does not start at 0

Anything you need to know about this, is here.

final class constants

Until now class constants could be overridden by child classes. With PHP 8.1 it is now possible to prevent this behavior by adding the final modifier to class constants. Here is an example showing this feature:

class Foo
{
    final public const X = "foo";
}
 
class Bar extends Foo
{
    public const X = "bar";
}
 
// Fatal error: Bar::X cannot override final constant Foo::X

And to know more about this is here.

New fsync et fdatasync methods

fsync et fdatasync are two new methods enforcing synchronization between the buffer and the physical storage. In other words this ensures a completed and persisted write before returning any success during a file change.

If the argument passed to fsync or fdatasync is not a valid pointer file, a warning will be emitted.

$fp = fopen('file.txt', 'w');
fwrite($fp, 'Hello world');

if (fsync($fp)) {
    echo "File successfully persisted on disk";
}

Here is the link for this feature.

Explicit octal integer literal notation

It is now possible to prefix numbers with 0o or 0O to denote octal numbers, in addition to the previous notation using only 0 .

0o16 === 14; // true
0o123 === 83; // true
 
0O16 === 14; // true
0O123 === 83; // true
 
016 === 0o16; // true
016 === 0O16; // true

Explicit octal notation is described here.

As we can see PHP 8.1 brings a bunch of new features. Make sure that your projects are fully tested against this version before deploying it to production.

Sebastian

Software Engineer · Web

Read his/her presentation

Do not miss any of our news

Every month, receive your share of information about us, such as the release of new articles or products.