PHP Property Hooks

PHP property hooks let a property define code that runs when you read or write it. Introduced in PHP 8.4, hooks reduce repetitive getter and setter methods while keeping property access direct and readable.

A property may define a get hook, a set hook, or both. You can use a backed property to store a value or a virtual property to calculate a value without storing it.

Create a Backed Property with a Set Hook

A backed property keeps its own value. Inside a set hook, assign the validated or normalized value to the property. The assignment targets the backing value and does not repeatedly call the same hook.

Example:

<?php

class Customer
{
    public string $email {
        set {
            // Normalize the address before storing it.
            $email = strtolower(trim($value));

            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
                throw new InvalidArgumentException("Invalid email address.");
            }

            $this->email = $email;
        }
    }
}

$customer = new Customer();
$customer->email = " [email protected] ";
echo $customer->email; // [email protected]

The implicit variable $value contains the value supplied by the caller. The declared property type still applies, so a value must also satisfy normal PHP type rules.

Use Short Hook Syntax

When a hook needs one expression, use the arrow form. It keeps small transformations compact without hiding complex logic.

Example:

<?php

class Product
{
    public float $price {
        // Prevent a negative stored price.
        set => max(0, $value);
    }
}

$product = new Product();
$product->price = -25;
echo $product->price; // 0

Create a Virtual Computed Property

A property is virtual when neither hook accesses its backing storage. A read-only computed value is a common use. The following fullName property derives its result from two stored properties.

Example:

<?php

class User
{
    public function __construct(
        public string $firstName,
        public string $lastName
    ) {}

    public string $fullName {
        // Calculate the value each time it is read.
        get => trim($this->firstName . " " . $this->lastName);
    }
}

$user = new User("Aarav", "Sharma");
echo $user->fullName; // Aarav Sharma

Because fullName has no set hook and no backing assignment, callers cannot store a separate full name through this property.

Define Both Get and Set Behavior

You can combine hooks when storage and presentation use different forms. This example stores a score within its allowed range and formats the read value.

Example:

<?php

class Review
{
    public int $rating {
        // Display a readable rating when accessed.
        get => $this->rating;

        // Store only a value from 1 through 5.
        set {
            if ($value < 1 || $value > 5) {
                throw new ValueError("Rating must be from 1 to 5.");
            }
            $this->rating = $value;
        }
    }
}

$review = new Review();
$review->rating = 5;
echo $review->rating;

Specify a Setter Parameter

You may name and type the setter parameter explicitly. Its accepted type can be broader than the property type, as long as the hook stores a value that satisfies the property declaration.

Example:

<?php

class Invoice
{
    public DateTimeImmutable $issuedAt {
        set(string|DateTimeImmutable $date) {
            // Accept a ready object or convert an ISO date string.
            $this->issuedAt = $date instanceof DateTimeImmutable
                ? $date
                : new DateTimeImmutable($date);
        }
    }
}

$invoice = new Invoice();
$invoice->issuedAt = "2026-09-01";
echo $invoice->issuedAt->format("Y-m-d");

Declare Property Requirements in an Interface

An interface can require readable or writable property behavior. An implementing class may satisfy the contract with a normal public property or compatible hooks.

Example:

<?php

interface Named
{
    // Implementations must expose a readable name.
    public string $name { get; }
}

class Employee implements Named
{
    public function __construct(
        public string $firstName,
        public string $lastName
    ) {}

    public string $name {
        get => $this->firstName . " " . $this->lastName;
    }
}

Property Hook Restrictions

Rule Reason
Hooks require PHP 8.4 or later Earlier PHP versions cannot parse the syntax.
Static properties cannot use hooks Hooks apply to object properties.
Readonly properties cannot use hooks Hook behavior conflicts with readonly storage rules.
Hooked properties cannot share one declaration Declare each hooked property separately.
A virtual property has no backing value Its hooks calculate or route the value elsewhere.

Tip: Keep hooks focused on property-level rules. Use a method when an operation performs database work, sends messages, or changes several parts of the object.

Conclusion

PHP property hooks place validation, normalization, and computed access beside the property they control. Use backed hooks for stored values, virtual hooks for derived values, and explicit setter parameters when callers may provide more than one input type. Apply hooks to small, predictable property behavior and keep larger business operations in methods.



Found This Page Useful? Share It!
Get the Latest Tutorials and Updates
Join us on Telegram