🐘
Hosting

What's New in PHP 8.4: Property Hooks, Asymmetric Visibility and More

06.11.2026
← All articles

PHP 8.4 was released in November 2024 and is one of the most noticeable updates in years. It brings property hooks, separate read and write visibility for properties, new array functions and a DOM API that parses HTML5 properly. Here is a practical walkthrough, followed by what to check before switching a hosted site to 8.4.

Property hooks: validation without getters and setters

Validating a value on write used to mean a private property plus getName() and setName() methods, which produced a lot of boilerplate. In PHP 8.4 the logic attaches directly to the property. Outside code still reads and writes a plain property, but your code runs on every access. Consider a product class for a small Tashkent online shop:

class Product
{
    public string $name {
        set(string $value) {
            $this->name = trim($value);
        }
    }

    public int $price {
        set(int $value) {
            if ($value < 0) {
                throw new InvalidArgumentException('Price cannot be negative');
            }
            $this->price = $value;
        }
    }

    // Virtual property: read-only, not stored
    public string $fullName {
        get => $this->name . ' - ' . number_format($this->price) . ' UZS';
    }
}

$p = new Product();
$p->name = '  Teapot  ';
$p->price = 85000;
echo $p->fullName; // Teapot - 85,000 UZS

$fullName is virtual: nothing is stored and the value is computed on each read. Hooks can also be declared in interfaces, so an interface can now require properties, not just methods.

Asymmetric visibility

Often a property should be readable by everyone but writable only by the class itself, such as an order status that changes only through a method:

class Order
{
    public private(set) string $status = 'new';

    public function pay(): void
    {
        $this->status = 'paid';
    }
}

$o = new Order();
$o->pay();
echo $o->status;          // paid
$o->status = 'cancelled'; // Error: cannot modify from outside

protected(set) also allows child classes to write.

New array functions and smaller conveniences

array_find(), array_find_key(), array_any() and array_all() replace many foreach loops. In a clinic booking system you can write array_find($appointments, fn($a) => !$a['confirmed']) to get the first unconfirmed appointment, or array_all($appointments, fn($a) => $a['confirmed']) to check whether everything is confirmed.

You can now chain on new without wrapping parentheses: new DateTimeImmutable()->format('Y-m-d'). Multibyte-safe mb_trim(), mb_ltrim(), mb_rtrim(), mb_ucfirst() and mb_lcfirst() help with Cyrillic and Uzbek text. The #[\Deprecated] attribute lets you mark your own functions as deprecated. The new Dom\HTMLDocument class parses HTML5 like a browser and supports CSS selectors, and lazy objects, aimed mainly at frameworks, delay object creation until first use.

Deprecations and removed extensions

Moving a hosted site to 8.4

For an existing site the main gains are speed and a longer security support window. Confirm that your CMS, theme and plugins support 8.4, back up files and the database, and test on a copy if possible. On sayt.uz hosting the PHP version is selected per site in ISPmanager, so switching one site does not affect the others. Watch the error log for a couple of days afterwards. A Fatal error means switching back and fixing the code calmly; Deprecated notices alone do not stop the site, but they may become errors in future versions.

Related articles

🟢 Deploying a Nuxt App: SSR, Static Generation, PM2 and Nginx 📧 How to Create and Set Up a Mailbox in ISPmanager 🚀 Zero-downtime deploys with release folders and a symlink switch 🔀 Managing Node.js Versions with nvm: Install, Switch and .nvmrc
🌐 Language
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English ✓