Code

What's new in PHP 8.1, features and improvements

Back to the blog

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.


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 https://www.php.net/manual/fr/migration81.php.

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 https://wiki.php.net/rfc/pure-intersection-types

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 https://wiki.php.net/rfc/noreturn_type

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:

  • comme les classes, les énumérations peuvent définir des méthodes. Il est également possible de définir des méthodes statiques.
  • 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 https://wiki.php.net/rfc/enumerations

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 https://wiki.php.net/rfc/fibers.

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 https://wiki.php.net/rfc/array_unpacking_string_keys

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 https://wiki.php.net/rfc/readonly_properties_v2

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 https://wiki.php.net/rfc/first_class_callable_syntax

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: https://wiki.php.net/rfc/is_list

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, https://wiki.php.net/rfc/final_class_const

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 https://wiki.php.net/rfc/fsync_function

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 https://wiki.php.net/rfc/explicit_octal_notation

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.

Author

Published on the 09 December 2021

Full Stack Developer