f in x
PHP 8.4: Property Hooks, Asymmetric Visibility, and Lazy Objects — Practical Guide
> cd .. / HUB_EDITORIALE
Analisi dei dati e metriche

PHP 8.4: Property Hooks, Asymmetric Visibility, and Lazy Objects — Practical Guide

[2026-05-29] Author: Ing. Calogero Bono

Have you ever written dozens of manual getters and setters in a PHP class? Or had to initialize a heavy object on every request even when it wasn't needed? PHP 8.4 solves exactly these problems with three features that change how you write clean, performant code: Property Hooks, Asymmetric Visibility, and Lazy Objects.

We, at Meteora Web, have been working with PHP for years — on WordPress, Laravel, custom platforms. We know how much time is wasted writing boilerplate or manually optimizing lazy loading. PHP 8.4 bakes these capabilities directly into the language. Let's see how they work and, more importantly, when to use them.

Property Hooks: Goodbye Manual Getters and Setters

If you've ever worked with classes that expose public properties but require validation or transformation logic, you know the classic solution was to write get/set methods. With PHP 8.4 you can define hooks directly on properties, just like in C# or Kotlin.

Before: The Old Way

class User {
    private string $name;

    public function getName(): string {
        return ucfirst($this->name);
    }

    public function setName(string $value): void {
        if (strlen($value) < 2) {
            throw new \InvalidArgumentException('Name too short');
        }
        $this->name = trim($value);
    }
}

After: Property Hooks

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

    // Validation in the hook itself
    public string $email {
        set {
            if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
                throw new \InvalidArgumentException('Invalid email');
            }
            $this->email = strtolower($value);
        }
    }
}

The code is more compact, and the logic stays attached to the property. No more scattered methods. One caveat: hooks cannot be used on static or untyped properties. Also watch out for inheritance — hooks can be overridden but with strict rules (the property must maintain the same type).

Action Item

Pick one of your most-used classes (e.g., a Laravel model or a DTO) and replace classic getters with Property Hooks. You'll write less code and make the logic more readable.

Asymmetric Visibility: Read-Public, Write-Private Properties

How many times have you wanted a property readable from the outside but writable only from inside the class? Previously you had to use getter methods and private setters. With PHP 8.4 you can declare two levels of visibility on the same property.

class Product {
    public private(set) string $sku;

    public function __construct(string $sku) {
        $this->sku = $sku; // only allowed here
    }
}

$product = new Product('ABC-123');
echo $product->sku; // OK
$product->sku = 'XYZ'; // Error: write access is private

You can use public protected(set) or protected private(set) for different levels. This feature makes design intentions explicit without resorting to defensive patterns.

When to Use It

  • Immutable IDs after creation (e.g., entity UUIDs)
  • Computed values that should be readable but not modifiable from outside
  • Configuration properties you want to expose as read-only

Lazy Objects: Heavy Objects Only When Needed

Lazy loading isn't new in PHP, but before PHP 8.4 you had to implement it manually or use libraries like Proxy Manager. Now the language itself provides Lazy Objects via the \LazyGhostTrait or the \lazy_object function.

The Concrete Problem

Imagine an object that loads data from a database or an API at construction time. If you don't always need it, you're wasting resources. With Lazy Objects, the instance is created only on the first access to a property or method.

class HeavyService {
    public function __construct() {
        // Simulate heavy loading
        file_get_contents('https://api.example.com/large-data');
    }

    public function doWork(): string {
        return 'Done';
    }
}

// Create a Lazy Ghost without calling the constructor
$lazyService = \lazy_object(HeavyService::class);

// Constructor is executed only here
$result = $lazyService->doWork();

You can also define a custom initializer to avoid running the standard constructor:

$lazy = \lazy_object(HeavyService::class, function() {
    // Custom initialization
    $instance = new HeavyService('cache_value');
    return $instance;
});

Ghost vs Virtual Proxy

PHP 8.4 offers two modes: Ghost (the object looks normal but is empty until touched) and Virtual Proxy (a wrapper that delegates to a real object when needed). For most cases, Ghost is simpler and more transparent.

Action Item

Identify a service in your application that is instantiated often but rarely used (e.g., an API client for a secondary endpoint). Wrap it in a Lazy Object and measure the reduction in bootstrap time.

Practical Considerations: When Not to Use Them

PHP 8.4 features aren't silver bullets. Property Hooks can obscure code if overused — stick to using them where real validation or transformation logic exists. Asymmetric Visibility is great for DTOs and Value Objects, but too many properties with different visibilities can hurt readability. Lazy Objects only make sense for truly expensive objects; don't apply it to everything.

We, at Meteora Web, started introducing them gradually in our Laravel projects. Our advice: upgrade to PHP 8.4, test in a staging environment, and start with a small class. The risk of regressions is minimal if your code is already well-typed.

In Summary — What To Do Now

  1. Upgrade PHP to at least 8.4 on your dev environment (see php.net for instructions).
  2. Replace a classic getter/setter with Property Hooks in a domain class.
  3. Make a property immutable using Asymmetric Visibility (public private(set)).
  4. Apply Lazy Object to a heavy service that loads external data.
  5. Monitor performance and readability gains with your usual profiling tools.

PHP 8.4 isn't just a minor update — these three features change how you design classes. Use them well, and your code will be cleaner, safer, and more performant.

Sponsored Protocol

Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Co-founder di Meteora Web. Ingegnere informatico, sviluppo ecosistemi digitali ad alte prestazioni. AI, automazione, SEO tecnica e infrastrutture web. Scrivo di tecnologia per rendere complesso… semplice.

[ Read Full Dossier ]

Hai bisogno di applicare questa strategia?

Esegui il protocollo di contatto per iniziare un progetto con noi.

> INIZIA_PROGETTO

Sponsored

> MW_JOURNAL

> READ_ALL()