Enums rfc

Enums will be added in PHP 8.1! If you’re unsure what they can be used for, you can read about them here.

Adding enums would be a significant improvement in PHP, so I for one am very much looking forward to seeing enums arrive in PHP 8.1. To give you a quick preview of what they will look like, here’s a code sample:

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

And this is how they will be used:

class Post
{
    public function __construct(
        private Status $status = Status::Pending;
    ) {}
 
    public function setStatus(Status $status): void
    {
        // …
    }
}
 
$post->setStatus(Status::Active);

You can find an in-depth analysis of how to use enums in this post.

Array unpacking with string keys rfc

Array unpacking was already allowed in PHP 7.4, 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 in initializers rfc

This RFC allows you to use the new keyword in function definitions as a default parameter, as well as in attribute arguments and other places.

class MyController {
    public function __construct(
        private Logger $logger = new NullLogger(),
    ) {}
}

Readonly properties rfc

Class properties can be marked as readonly, meaning they can only be written once.

class PostData {
    public function __construct(
        public readonly string $title,
        public readonly DateTimeImmutable $date,
    ) {}
}

Trying to change a readonly property after it has been initialized will result in an error:

$post = new Post('Title', /* … */);
 
$post->title = 'Other';
 
Error: Cannot modify readonly property Post::$title

Pure intersection types rfc

You already know about union types in PHP 8.0, and intersection types are a similar feature. Where union types require the input to be one of the given types, intersection types require the input to be all of the specified types. Intersection types are especially useful when you’re working with lots of interfaces:

function generateSlug(HasTitle&HasId $post) {
    return strtolower($post->getTitle()) . $post->getId();
}

If you like this style of programming, you’d need to create a new interface Sluggable and implement it in $post, intersection types get rid of that overhead.

Final class constants rfc

Class constants in PHP can be overridden during inheritance:

class Foo
{
    public const X = "foo";
}
 
class Bar extends Foo
{
    public const X = "bar";
}

As of PHP 8.1, you can mark such constants as final in order to prevent this:

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
}