PHP 8.1 new feature usagePHP 8.1 features, one year later

Closing on one year after PHP 8.1 publication, we can take a look at the published features, and how they are doing in current code.

Let’s take the list of ‘PHP Core’ from the New Features ¶.

Project corpus

We’ll use that against the Exakat corpus, with 2696 PHP open source projects. Out of those, 1511 were updated since last year, (56%). Those projects had a chance to update their code base to be compatible with PHP 8.1, and then, adopt those features.

Feature adoption

The PHP 8.1 features are all backward incompatible : adopting them means that the code cannot be run anymore on older version, including PHP 8.0. In the case of Open Source projects, with long eras of support, this means that the absolute figures will be much lower than against closed code.

The relative adoption of the features shows it popularity and is the most interesting part of this review.

That said, let’s dive.

Integer Octal Literal Prefix

014 being equivalent to 0o14 was adopted by 2 projects, including exakat itself for testing purposes. Generally speaking, octals are not common, being used by 34% of the projects, and primarily with mkdir() and related functions.

Array Unpacking with String Keys

This was not tracked by audits so far. It is easily hidden by decoded strings, dynamic code and databases responses. Some research is still needed in this area.

$arr1 = [1, 'a' => 'b'];
$arr2 = [...$arr1, 'c' => 'd']; //[1, 'a' => 'b', 'c' => 'd']

Named Argument After Argument Unpacking

This is not detected in any codes so far. For comparison, named parameters are used by 253 projects (16.7%).

foo(...$args, named: $arg);

full-path Key for File Uploads

This is not detected in any codes so far.


Enumeration are used by 151 projects (10%).

enum Suit
    case Hearts;
    case Diamonds;
    case Clubs;
    case Spades;


Fibers are used by 81 projects, so roughly 5.6 %.

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

$value = $fiber->start();

echo "Value from fiber suspending: ", $value, PHP_EOL;


First Class Callable Syntax

First class callable are used by 201 projects (13.3%).

Those are simpler syntax for closures creation.

// traditional callable using string, array
$fcc = strlen(...);

$closure = Closure::fromCallable('strlen');


Intersection Types

Support for intersection types has been added.

Intersection types were adopted by 84 projects (5.6 %). Most of them are used with the poster child type of \Traversable&\Countable. Other cases are Mock objects (thanks to Arnout Boks).

Never type

The never type indicates that a function either exit(), throws an exception, or doesn’t terminate.

Never type were adopted by 43 projects, so roughly 2.9 %.

new in Initializers

New in initializers is the usage of new within PHP static expressions and define() calls for properties, and parameters.

New in initializer are used by 241 projects (15.9 %).

Readonly properties

Support for properties that can be written once, then only read has been added.

Readonly properties are now in use by 124 projects (8.2 %).

Final class constants

Final keyword is now compatible with constants. They are already used in 14 projects (0.9 %).

Final round up

The top 3 PHP 8.1 features are :

  • New in initializers 15.9%
  • First class callable 13.3%
  • Enumerations 10%.

Then, come readonly, intersection type and fiber.

Recent statistics place PHP 8.1 adoption between 20% and 30%. With 15.9%, ‘new in initializer’ is actually adopted half the time, once PHP 8.1 has been upgraded. Enumerations are up to a 33%. These are good levels of adoption, one year later.

It seems to me that ‘new in initializer’ is a very productive feature, with the potential to upgrade significantly our code with the null object pattern. Yet, there are not many tutorials and blogs about them. Did we miss them ?