PHP 8.1: before and after

The release of PHP 8.1 will be here within a few months, and once again there are many features that get me excited! In this post I want to share the real-life impact that PHP 8.1 will have on my own code.

# Enums

A long-awaited feature, enums are coming! There's little to be said about this one, besides that I'm looking forward to not having to use spatie/enum or myclabs/php-enum anymore. Thanks for all the years of enum support to those packages, but they are the first I'll ditch when PHP 8.1 arrives and when I change this:

/**
 * @method static self draft()
 * @method static self published()
 * @method static self archived()
 */
class StatusEnum extends Enum
{
}

PHP 8.0

To this:

enum Status
{
    case draft;
    case published;
    case archived;
}

PHP 8.1

# Array unpacking with string keys

This one might seem like a small one, but it has bothered me more than once: only list arrays could be unpacked before PHP 8.1:

$a = [1, 2, 3];
$b = [4, 5, 6];

// This is allowed
$new = [...$a, ...$b];

PHP 8.0

While arrays with string keys cannot:

$a = ['a' => 1, 'b' => 2, 'c' => 3];
$b = ['d' => 4, 'e' => 5, 'f' => 6];

$new = [...$a, ...$b]; 

// You'd need to use array_merge in this case
$new = array_merge($a, $b); 

PHP 8.0

And so, one of the great features of PHP 8.1 that will make my life easier, is that arrays with string keys can now be unpacked as well!

$a = ['a' => 1, 'b' => 2, 'c' => 3];
$b = ['d' => 4, 'e' => 5, 'f' => 6];

// :)
$new = [...$a, ...$b]; 

PHP 8.1

Noticed a tpyo? You can submit a PR to fix it. If you want to stay up to date about what's happening on this blog, you can subscribe to my mailing list: send an email to brendt@stitcher.io, and I'll add you to the list.

# Class properties: initializers and readonly

Another stunning new feature is once again such a quality-of-life improvement that I've struggled with for years: default arguments in function parameters. Imagine you'd want to set a default state class for a BlogData object. Before PHP 8.1 you'd have to make it nullable and set it in the constructor:

class BlogData
{
    public function __construct(
        public string $title,
        public ?BlogState $state = null,
    ) {
        $this->state ??= new Draft();
    }
}

PHP 8.0

PHP 8.1 allows that new call directly in the function definition. This will be huge:

class BlogData
{
    public function __construct(
        public string $title,
        public BlogState $state = new Draft(),
    ) {
    }
}

PHP 8.1

Speaking of huge, have I mentioned yet that readonly properties are a thing now?!?

class BlogData
{
    public function __construct(
        public readonly string $title,
        public readonly BlogState $state = new Draft(),
    ) {
    }
}

PHP 8.1

Oh and don't worry about cloning, by the way: I've got you covered.

# First-class callable syntax

As if that wasn't enough, there's now also the first-class callable syntax, which gives you a clean way of creating closures from callables.

Previously you'd had to write something like this:

$strlen = Closure::fromCallable('strlen');
$callback = Closure::fromCallable([$object, 'method']);

PHP 8.0

In PHP 8.1, you can do… this:

$strlen = strlen(...);
$callback = $object->method(...);

PHP 8.1


There are even more features in PHP 8.1, but these are the ones I'm most excited about. What's your favourite one? Let me know on Twitter!