New Features Coming in PHP 8.1

by PushRadar on April 17, 2021

PHP 8.1 is the next version of PHP, currently in development and scheduled to be released later in 2021, with the current release date set as November 25.

Building upon a host of improvements that made it into PHP 8, PHP 8.1 will add some nifty new features, as well as generally non-breaking changes to existing functionality and some deprecations. In this blog post we will take a look at these updates, with a specific focus on the new and exciting developments which you’ll be able to take advantage of in the not-to-distant future.

First up on our list of new PHP 8.1 features, Enums!

For those of you that don’t know what an enum (or enumeration) is, let’s start with an example. Imagine you are making a blogging platform. You’ve written a BlogPost class. Each blog post can be in one of three states, ‘draft’, ‘published’ or ‘archived’. This is a prime example of where you could use a PostState enum to represent the states. This can be done using new syntax in PHP 8.1 as follows:

PHP
enum PostState {
    case DRAFT;
    case PUBLISHED;
    case ARCHIVED;
}

From your BlogPost class, you could then have a $state property with the type set to PostState:

PHP
class BlogPost
{
    public function __construct(
        public PostState $state
    ) {}
}

// $post = new BlogPost(PostState::DRAFT);

Enums are just a collection of predefined options (cases). Here, using enums avoids the need for additional validation over whether the passed post state is acceptable; you can be sure that the post state is one of the three allowed values.

Enums can have from zero to infinite cases specified. At their core, enums are objects and they can be treated much in the same way as regular classes. They can implement interfaces like classes, and they can also be used with traits (as long as the trait does not contain properties).

Enum cases can be backed by simpler scalar values. If an enum’s cases are backed, the enum is called a Backed Enum. The following is an example of a Backed Enum:

PHP
enum PostState {
    case DRAFT = 'draft';
    case PUBLISHED = 'published';
    case ARCHIVED = 'archived';
}

Other languages such as C# have had enums for a long time; we think that this feature is a welcome addition to PHP and a feature that will be useful in a variety of situations.

The never Return Type

Next up, let’s have a look at another new addition to PHP 8.1.

With PHP 8.1, a new never return type will be added. never can be used as the return type in a method that terminates program flow either by exiting or throwing an exception. It is specifically designed to signal to callers that the method:

  • does not return a value; and
  • will end program flow without returning to the caller.

never can only be used as a return type; it cannot be used as a property type, for instance.

Here is an example of the never type being used in action:

PHP
function addNumbers(int $a, int $b): never
{
    $c = $a + $b;
    exit();
}

addNumbers(4, 8); // doesn't return, program flow is terminated

Fibers

PHP 8.1 introduces a new Fiber class. Fibers are low level constructs that essentially make it possible to run code blocks apart from the main code. Such code blocks can maintain their own state and be started, paused and stopped completely.

A Fiber cannot start itself – that’s a responsibility of the main code. The code block in a Fiber can, however, return data back to the main program and suspend itself at any given moment. Resuming a Fiber from where it was suspended is possible, but only the main code can initiate this.

It’s important to realise that Fibers do not allow for simultaneous execution. The main code and the Fiber’s code do not run simultaneously. Once a Fiber is started, it is run exclusively.

Fibers are more of an implementation detail for event-driven, non-blocking IO libraries such as ReactPHP and it is probably unlikely that you will come to use them directly in your code, but it’s worthwhile knowing that they exist.

Here is a code example of Fibers in action. If you’re coming from other languages such as C#, you may note that Fibers are similar to threads:

PHP
$f = new Fiber(function() {
    // ... code after being started
    Fiber::suspend();
    // ... code after being resumed
});

$f->start();
// ... flow transfers to Fiber, until Fiber is suspended, then ...
$f->resume();

Array Unpacking – Support for String Keys

In PHP 8.1, array unpacking will support string keys, with duplicate keys handled in the same way as when using the array_merge function (keys overwritten by latest instance).

Here’s an example of array unpacking with string keys:

PHP
$array1 = ["a" => 1];
$array2 = ["a" => 2];
$array = ["a" => 0, ...$array1, ...$array2];
var_dump($array); // ["a" => 2]

New array_is_list Method

If you have ever had to check if an array has numerical keys in ascending order starting at 0, this function is for you. array_is_list is getting added in PHP 8.1 and it will check whether the array passed as its first parameter has sequential integer keys, i.e. keys that ascend from zero without missing any numbers (0, 1, 2, 3, 4 …). Here’s a couple of examples of how it can be used:

PHP
array_is_list([1, 2, 3]); // true
array_is_list(['cake', 'biscuit']); // true
array_is_list([0 => 'cake', 1 => 'biscuit']); // true
array_is_list([0 => 'cake', 2 => 'biscuit']); // false

New fsync and fdatasync Methods

Two other new methods that will be added in PHP 8.1 are fsync and fdatasync. These methods instruct the application to flush its internal buffers to physical storage (without necessarily syncing metadata in the case of fdatasync).

fsync essentially synchronises to disk before returning, in comparison to the existing function fflush which just instructs the application to flush its internal buffers out to the OS. As such, fsync can only be used with disk file streams and no other type of stream.

Here is an example of usage:

PHP
$file = 'example.txt';
$handle = fopen($file, 'w');
fwrite($handle, 'some data');
fsync($handle); // sync to filesystem
fclose($handle);

Changes to $GLOBALS Usage

PHP 8.1 introduces changes to how $GLOBALS can be used. This may, in some circumstances, require your code to be changed, so best to prepare for it in advance. After the upcoming release, $GLOBALS will not be able to be written to or passed by reference. The following will produce a runtime error:

PHP
$GLOBALS = [];
$GLOBALS += [];
$GLOBALS =& $x;
$x =& $GLOBALS;
unset($GLOBALS);

However the following will still work:

PHP
$GLOBALS['x'] = 1;
$GLOBALS['x']++;
isset($GLOBALS['x']);
unset($GLOBALS['x']);

From the RFC:

The $GLOBALS variable currently provides a direct reference to PHP’s internal symbol table. Supporting this requires significant technical complexity, affects performance of all array operations in PHP, but is only rarely used.

It appears that changing the allowed usage of $GLOBALS will positively impact the performance of array operations in general. It’s a good trade-off for compatibility since most code will continue to work as-is.

Deprecations & Minor Changes

Quite a few minor changes will also be released as part of PHP 8.1. Internal functions that have been accepting null for non-nullable parameters will now throw a deprecation warning, htmlspecialchars and htmlentities will now escape the apostrophe character as well as other characters which previously were un-escapable, and the hash, hash_file and hash_init functions have been modified to accept an additional optional $options parameter (non-breaking changes).

There are also some performance improvements which should make it into the final release.

Flexible realtime pub-sub API

Try PushRadar free for 5 days