← Back to engineering
#php

PHP 8.4 released

By Krodox Team 3 min read

PHP 8.4 is the release that finally removed a great deal of getter-and-setter boilerplate from PHP. Here are the features that matter in practice, with examples.

Key features in PHP 8.4

1. Property hooks

The headline addition. Properties can now intercept their own reads and writes, without the class needing an explicit getter and setter pair.

class Locale
{
    public string $languageCode;

    public string $countryCode {
        set (string $countryCode) {
            $this->countryCode = strtoupper($countryCode);
        }
    }

    public string $combinedCode {
        get => sprintf('%s_%s', $this->languageCode, $this->countryCode);
        set (string $value) {
            [$this->languageCode, $this->countryCode] = explode('_', $value, 2);
        }
    }

    public function __construct(string $languageCode, string $countryCode)
    {
        $this->languageCode = $languageCode;
        $this->countryCode = $countryCode;
    }
}

$brazilianPortuguese = new Locale('pt', 'br');
var_dump($brazilianPortuguese->countryCode); // BR
var_dump($brazilianPortuguese->combinedCode); // pt_BR

The second property is computed on read and decomposed on write, and callers just treat it as a property. A large amount of accessor code exists purely to normalise a value on the way in; this deletes most of it.

2. Asymmetric visibility

Read and write access can now differ, which expresses "public to read, private to change" without writing a getter for it.

class PhpVersion
{
    public private(set) string $version = '8.4';
}

This pairs naturally with property hooks: hooks control how a property is read or written, asymmetric visibility controls who may do it.

3. The #[\Deprecated] attribute

Deprecation stops being a docblock convention and becomes something the engine and your tooling understand.

class PhpVersion
{
    #[\Deprecated(
        message: 'use PhpVersion::getVersion() instead',
        since: '8.4',
    )]
    public function getPhpVersion(): string
    {
        return $this->getVersion();
    }

    public function getVersion(): string
    {
        return '8.4';
    }
}

4. A modern DOM API with HTML5 support

The old DOM extension predates HTML5 and showed it. PHP 8.4 adds a new API that parses HTML5 correctly and supports CSS selectors:

$dom = Dom\HTMLDocument::createFromString($html, LIBXML_NOERROR);

$node = $dom->querySelector('main > article:last-child');

var_dump($node->classList->contains('featured'));

If you have ever reached for a scraping library purely because DOMDocument mangled modern markup, this is the fix.

5. New array functions

array_find(), array_find_key(), array_any() and array_all() cover the four things everyone previously wrote a foreach for.

$featured = array_find($articles, fn ($article) => $article->featured);

if (array_any($articles, fn ($article) => $article->draft)) {
    // ...
}

6. BCMath object API

Arbitrary-precision numbers become real objects with operator support, rather than strings passed through bcadd() and friends.

use BcMath\Number;

$total = new Number('0.12345') + new Number('2');

7. Smaller quality-of-life changes

Method chaining no longer requires wrapping parentheses around new:

var_dump(new PhpVersion()->getVersion());

PDO also gained driver-specific subclasses (Pdo\Sqlite, Pdo\MySql, Pdo\Pgsql), so driver-specific behaviour is expressed in the type system rather than in documentation.

Why upgrade

  1. Less boilerplate. Property hooks and asymmetric visibility remove a category of code that existed only to guard a property.
  2. Better tooling signals. #[\Deprecated] is machine-readable, so static analysis can act on it.
  3. Fewer workarounds. The new DOM API and the array functions replace common third-party dependencies.
  4. Support runway. Staying current is what keeps future upgrades cheap.

Where it fits now

PHP 8.4 remains a workable target, but its active support ends on 31 December 2026 (security fixes continue until 31 December 2028), so PHP 8.5 is the better target for new work. Laravel 13 supports PHP 8.3 through 8.5, so 8.4 still sits comfortably in the supported range.

PHP 8.5 is out and adds the pipe operator, clone with, and a built-in URI parser.

As always, test before upgrading rather than after.

Related reading

We use cookies to enhance your experience and keep your data secure. Privacy Policy