Backend Development

PHP 8.4 Property Hooks: A Modern Alternative to Getters and Setters

PHP 8.4 Property Hooks: A Modern Alternative to Getters and Setters

PHP 8.4 introduces Property Hooks, one of the most significant object-oriented programming features added to PHP in years. Property hooks allow developers to attach logic directly to property reads and writes while preserving the natural property access syntax.

 

 

 

What Are Property Hooks?

Traditionally, PHP properties are simple storage containers:

class User 
{ 
    public string $name; 
}

Reading or writing the property performs no additional logic:

$user = new User(); 
$user->name = 'John'; 
echo $user->name;

Property hooks change this by allowing you to intercept property access:

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

Whenever a value is assigned to $name, the hook runs automatically.

The syntax feels similar to property accessors found in languages such as C#, Kotlin, and Swift.

 

Why Were Property Hooks Added?

For years, PHP developers often wrote boilerplate code like this:

class User 
{ 
      private string $name; 

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

      public function setName(string $name): void 
      { 
         $this->name = ucfirst(trim($name)); 
      } 
}

This works, but introduces a lot of repetitive code.

Property hooks reduce that boilerplate:

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

Usage remains simple:

$user->name = ' john '; 
echo $user->name; // John

 

Understanding the set Hook

The most common use case is validating or transforming values before storing them.

Validation Example:

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

Now invalid assignments are prevented:

$product->price = -10; // Exception

Data Normalization Example:

class User 
{ 
    public string $email 
    { 
         set => strtolower(trim($value)); 
    } 
}

Assignments become automatically normalized:

$user->email = ' John@Example.COM '; 

echo $user->email; // john@example.com

 

Understanding the get Hook

A get hook allows a custom behavior whenever a property is read.

class Temperature 
{ 
     private float $celsius = 25; 

     public float $fahrenheit 
     { 
        get => ($this->celsius * 9 / 5) + 32; 
     } 
}

Reading the property computes the value dynamically:

$temp = new Temperature(); 

echo $temp->fahrenheit; // 77

This creates a property-like API while hiding implementation details or what it called computed property.

 

Full get and set Hooks

You can define both hooks on the same property.

class Person 
{ 
     private string $fullNameStorage = ''; 
    
     public string $fullName 
     { 
         get => $this->fullNameStorage; 
         
         set => trim($value); 
     } 
}

This gives complete control over reads and writes.

 

Backed vs Virtual Properties

Property hooks support two different styles.

Backed Properties

A backed property stores data internally.

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

The property still exists physically.

 

Virtual Properties

A virtual property has no actual storage and computes its value entirely through hooks.

class Rectangle
{
    public int $width;
    public int $height;

    public int $area {
        get => $this->width * $this->height;
    }
}

There is no separate $area field.

echo $rectangle->area;

The value is generated on demand.

 

Practical Use Cases:

1.Input Validation

public int $age {
    set {
        if ($value < 0) {
            throw new InvalidArgumentException();
        }

        $this->age = $value;
    }
}

2.Data Sanitization

public string $username {
    set => trim($value);
}

3.Computed Values

public float $total {
    get => $this->price * $this->quantity;
}

4.Lazy Calculations

public string $slug {
    get => strtolower(
        str_replace(' ', '-', $this->title)

        );
}

5.Domain Rules

public string $status {
    set {
        $allowed = [
            'draft',
            'published',
            'archived'
        ];

        if (!in_array($value, $allowed)) {
            throw new InvalidArgumentException();
        }

        $this->status = $value;
    }
}

 

Do Property Hooks Replace Getters and Setters?

Sometimes, but not completely.

Property hooks can eliminate many traditional getter and setter methods.
For example, instead of:

$user->setEmail('john@example.com');

you can write:

$user->email = 'john@example.com';

And instead of:

echo $user->getEmail();

you can write:

echo $user->email;

This produces cleaner and more expressive code.

When Property Hooks Are Better

Property hooks shine when:

  • Performing validation
  • Normalizing data
  • Computed values
  • Reducing boilerplate.

When Getters and Setters still make sense

Property hooks are not a complete replacement.

Consider this method:

public function publish(): void
{
    if (!$this->isApproved()) {
        throw new RuntimeException();
    }

    $this->status = 'published';
}

This is business behavior, not property access.

Similarly:

$order->cancel();
$user->activate();
$post->publish();

represent actions and workflows. These should remain methods.

A good rule of thumb: Property Hooks = property-related logic, Methods = business operations.

 

0 0 votes
Article Rating

What's your reaction?

Excited
0
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted