Implement property hooks in PHP 8.4

PHP 8.4 introduces a new feature called property hooks, which allows you to modify class property values with special hooks.

M Bytes Newsletter
Get the developer newsletter

    Fresh bytes every Thursday. No spam, ever. Unsubscribe anytime.

    Join 9,000+ developers and get three free video lessons every week.

    PHP 8.4 introduced a new feature called property hooks. It’s exactly what it sounds like — it allows you to modify a property’s value with special hooks.

    To understand how it works, it makes sense for us to look at how we would validate property values before PHP 8.4 with traditional getters and setters:

    <?php
     
    class Product
    {
        private float $price;
     
        public function getPrice(): float
        {
            return $this->price;
        }
     
        public function setPrice(float $price): void
        {
            if ($price < 0) {
                throw new InvalidArgumentException('Price cannot be negative');
            }
     
            $this->price = $price;
        }
    }

    Let’s transform this code into a much more elegant version.

    Rather than simply defining the property visibility on this line, we’ll open it up with some curly braces, and also change the visibility to public:

    <?php
     
    class Product
    {
        public float $price {
            // We'll add our hooks here
        }
    }

    Even though the property is public, we can control the access to this property with hooks.

    Let's start with the getter hook:

    <?php
     
    class Product
    {
        public float $price {
            get {
                return $this->price;
            }
     
            // We could also use arrow syntax:
            // get => $this->price;
        }
    }

    The syntax for hooks look like functions. We don’t have any parameters here, so we can eliminate the parenthesis.

    We could also use PHP’s arrow syntax to shorten this logic to a single line when we we simply return a value.

    Now let’s look at our setter:

    <?php
     
    class Product
    {
        public float $price {
            get => $this->price;
            set (float $value) {
                if ($value < 0) {
                    throw new InvalidArgumentException('Price cannot be negative');
                }
     
                $this->price = $value;
            }
        }
    }
     

    The set hook syntax is similar to our getter, but it receives a value as a parameter. We can then define all of our business logic within this hook, just like our traditional setter.

    Implementing property hooks also feels way more natural:

    <?php
     
    $product = new Product();
     
    $product->price = 100;  // Works fine
     
    echo $product->price;   // Outputs: 100
     
    $product->price = -50;  // Throws error: Price cannot be negative

    Notice how we're now working directly with the price property — rather than calling setPrice() or getPrice(), we can use the clean syntax of public properties, but without sacrificing the safety of getters and setters.

    Pro tip: Property hooks work best for straightforward validation. For complex logic or when you need to work with multiple properties, traditional getters and setters might still be your best choice.