What's new in PHP 8.4

PHP 8.4 will be released on November 21, 2024. It'll include property hooks, JIT improvements, as well as chaining methods on new without additional parentheses — a big one!


# Property hooks RFC

One of the biggest changes in modern-PHP history: the ability to define property hooks, eliminating the need for a lot of boilerplate code.

class BookViewModel
{
    public function __construct(
        private array $authors,
    ) {}

    public string $credits {
        get {
            return implode(', ', array_map(
                fn (Author $author) => $author->name, 
                $this->authors,
            ));
        }
    }
    
    public Author $mainAuthor {
        set (Author $mainAuthor) {
            $this->authors[] = $mainAuthor;
            $this->mainAuthor = $mainAuthor;
        }
        
        get => $this->mainAuthor;
    }
}

The goal of property hooks is to remove a lot of getters and setters, by allowing each property to define its own get and set hooks. Hooks are optional, and you don't have to add both of them on a specific property. For example, a property with only a get hook is virtual property.

There is a lot to say about property hooks, and I plan to write a followup post on them soon, so make sure to subscribe if you want to know when that one is done. One final thing I'd like to mention — probably what I'm most hyped about: property hooks can be defined in interfaces!

interface HasAuthors
{
    public string $credits { get; }
    public Author $mainAuthor { get; set; }
}

# new without parentheses RFC

As if property hooks alone wasn't enough, PHP 8.4 has another feature that will save so much boilerplate code: you don't have to wrap new invocations within parenthesis anymore to be able to chain methods on them. So instead of doing this:

$name = (new ReflectionClass($objectOrClass))->getShortName();

You can now do this:

$name = new ReflectionClass($objectOrClass)->getShortName();

I don't know about you, but I write a lot of code like this, and so I'm super happy that we're finally getting rid of those brackets. It doesn't only work for methods, by the way. You can also chain properties, static methods, constants — whatever you want.


# JIT changes RFC

PHP 8.4 changes the way the JIT is enabled. Previously, you had to set opcache.jit_buffer_size to 0 in order to disable the JIT, but now you can disable it like so:

opcache.jit=disable
opcache.jit_buffer_size=64m

The only way users can be affected by this change is if they did specify a opcache.jit_buffer_size but no opcache.jit. In that case, you'll have to add opcache.jit=tracing to enable the JIT again.

Finally, there have also been some improvements to the JIT which makes it run faster in some cases, and use less memory.


# Implicit nullable types deprecation

PHP had this weird behaviour where a typed variable with a default null value would be made nullable automatically:

function save(Book $book = null) {}

// Deprecated: Implicitly marking parameter $book as nullable is deprecated,
// the explicit nullable type must be used instead

This behaviour is now deprecated and will be removed in PHP 9. The solution is to make Book explicitly nullable:

function save(?Book $book = null) {}

# New DOM HTML5 support RFC

PHP 8.4 adds a \Dom\HTMLDocument class which is able to parse HTML5 code properly. The old \DOMDocument class is still available for backwards compatibility.

$doc = \Dom\HTMLDocument::createFromString($contents);

PHP 8.4 is still in the early development phase, so there's of course more to come. I'll update this post over time, so make sure to subscribe if you want to be kept in the loop.

If you want something to watch next, make sure to check out my latest video as well:

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.