What's new in PHP 8.1
Published: 2021-02-03 09:22:28

---
title: What's new in PHP 8.1
published: true
date: 2021-01-29 00:00:00 UTC
tags: 
canonical_url: https://stitcher.io/blog/new-in-php-81
---

PHP 8.1 is currently is active development and will probably be release somewhere around the end of November 2021. We already know some of the features, changes and deprecations, so let's go through them one by one.

Do you want to stay up-to-date about PHP 8.1's development? Subscribe to my newsletter and receive occasional updates:

## New features

As with every release, PHP 8.1 adds some nice new features. Keep in mind that this list will grow over the year. I'm also listing features that haven't been implemented yet but that make a good chance of ending up in the language. I'll make sure to always mark those features.

### Array unpacking with string keys

Array unpacking was already allowed in [PHP 7.4](/blog/new-in-php-74), but it only worked with numeric keys. The reason string keys weren't supported before is because there wasn't any consensus on how to merge array duplicates. The RFC cleanly solves this by following the semantics of `array_merge`:

```
$array1 = ["a" => 1];

$array2 = ["b" => 2];

$array = ["a" => 0, ...$array1, ...$array2];

var_dump($array); // ["a" => 1, "b" => 2]
```

### New `array_is_list` function

You've probably had to deal with this once in a while: determine if an array's keys are in numerical order, starting form index 0. Just like `json_encode` decides whether an array should be encoded as an array or object.

PHP 8.1 adds a built-in function to determine whether an array is a list with those semantics, or not:

```
$list = ["a", "b", "c"];

array_is_list($list); // true

$notAList = [1 => "a", 2 => "b", 3 => "c"];

array_is_list($notAList); // false

$alsoNotAList = ["a" => "a", "b" => "b", "c" => "c"];

array_is_list($alsoNotAList); // false
```

<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CK7ICK3W&amp;placement=stitcherio" id="_carbonads_js"></script>

### Explicit octal integer literal notation

You can now use `0o` and `0O` to denote octal numbers. The previous notation by prefixing a number with `0` still works as well.

```
016 === 0o16; // true
016 === 0O16; // true
```

### Enums

**This RFC is still under discussion.**

Even though there hasn't been a vote yet, this proposal to add enums has been received with enthusiasm. If you're unsure about the value they add, you can read about them [here](/blog/php-enums).

Adding enums would be a significant improvement in PHP, so I'm for one am very much looking forward seeing this RFC further evolve. To give you a quick preview of what they would look like, here's a code sample:

```
enum Status {
  case Pending;
  case Active;
  case Archived;
}
```

And this is how they would be used:

```
class Post
{
    public function __construct(
        private Status $status = Status::Pending;
    ) {}

    public function setStatus(Status $status): void
    {
        // …
    }
}

$post->setStatus(Status::Active);
```

## Breaking changes

While PHP 8.1 is a minor version, there will be some changes that might technically be a breaking change, and deprecations as well. Let's discuss them one by one.

### Restrict `$GLOBALS` usage 

A small change to how `$GLOBALS` is used will have a significant impact on the performance of all array operations. Nikita does a fine job explaining the problem and solution in the [RFC](https://wiki.php.net/rfc/restrict_globals_usage). The change means that some edge cases aren't possible to do anymore with `$GLOBALS`. "_What is no longer supported are writes to $GLOBALS taken as a whole. All of the following will generate a compile-time error_":

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

On top of that, passing `$GLOBALS` by reference will generate a runtime error:

```
by_ref($GLOBALS); // Run-time error
```

Nikita analysed the top 2000 packages on packagist, and only found 23 cases that will be affected by this change. We can conclude the impact of this — technically breaking — change will be low, which is why internals decided to add it in PHP 8.1. Remember that most of us will win by this change, given the positive performance impact it has everywhere in our code.

### Deprecate passing null to non-nullable arguments of internal functions

This change is simple: internal functions currently accept `null` for arguments that are non-nullable, this RFC deprecates that behaviour. For example, this is currently possible:

```
str_contains("string", null);
```

In PHP 8.1, these kinds of errors will throw a deprecation warning, in PHP 9 they will be converted to type errors.

* * *

That's it for now, keep in mind I'll regularly update this post during the year, so make sure to [subscribe](https://stitcher.io/newsletter/subscribe) if you want to be kept in the loop. Are you exited for PHP 8.1? Let me know on [Twitter](https://twitter.com/brendt_gd)!