PHP Typed Properties, Readonly Classes & Property Hooks: Modern OOP
Master PHP typed properties, readonly classes, and property hooks.
20+ years shipping production PHP systems at scale. Written from production experience, not tutorials.
- ✓Basic PHP syntax and OOP concepts
- ✓Familiarity with classes and objects
- ✓PHP 7.4+ installed (8.4 for property hooks)
- Typed properties enforce type at runtime, preventing invalid data.
- Readonly properties can only be set once, typically in constructor.
- Property hooks (PHP 8.4) allow custom get/set logic without methods.
- Combining these features leads to safer, more expressive code.
Think of a property like a labeled box. Typed properties say 'only put numbers here'. Readonly says 'once you put something, you can't change it'. Property hooks are like a smart box that runs a check or transformation whenever you put something in or take something out.
In modern PHP development, writing robust and maintainable code is paramount. One of the biggest leaps in that direction came with PHP 7.4's typed properties, which allow you to declare the exact type of data a class property can hold. No more guessing whether $user->name is a string or an object – the language enforces it at runtime. PHP 8.1 introduced readonly properties, which can only be assigned once, typically in the constructor, making immutable objects a breeze. And with PHP 8.4, property hooks are on the horizon, letting you add get/set logic directly on properties without writing separate methods. Together, these features transform how you design classes, making them more self-documenting, less error-prone, and easier to reason about. In this tutorial, you'll learn each feature inside out, see production-ready examples, and discover how to avoid common pitfalls. Whether you're building a simple DTO or a complex domain model, these tools will become your new best friends.
Typed Properties: The Basics
Typed properties allow you to declare the type of a class property. Supported types include scalar types (int, float, string, bool), arrays, iterable, object, mixed, and nullable types (prefixed with ?). You can also use class/interface names. Once declared, PHP will enforce that any value assigned to the property matches the type, throwing a TypeError if not. This catches bugs early and makes your code self-documenting.
Example: A simple User class with typed properties.
Nullable and Union Types
Sometimes a property can be null or multiple types. Use nullable types (e.g., ?string) or union types (e.g., int|string). Union types were introduced in PHP 8.0. They allow a property to accept multiple types, but be careful: too many union types can indicate a design flaw.
Example: A nullable email and a union type for a mixed value.
Readonly Properties: Immutability Made Easy
Readonly properties (PHP 8.1) can only be assigned once, typically in the constructor. After initialization, any attempt to modify them throws an Error. This is perfect for value objects, DTOs, and configuration objects. Readonly properties can be typed and can have default values. They cannot be unset.
Example: A readonly configuration class.
Property Hooks: Custom Get/Set Logic (PHP 8.4)
Property hooks, introduced in PHP 8.4, allow you to define custom get and set logic directly on a property, without writing separate getter and setter methods. This makes your code more concise and readable. The syntax uses get and set keywords inside the property declaration. The set hook receives the value to be assigned, and you can use $this->property to access the backing value.
Example: A property that always trims strings on set.
Combining Typed, Readonly, and Hooks
You can combine all three features for maximum safety and expressiveness. For example, a readonly property with a typed declaration and a get hook that computes a derived value. However, readonly properties cannot have set hooks because they are immutable. You can have a get hook on a readonly property.
Example: A readonly property that formats a date.
Common Pitfalls and Best Practices
- Uninitialized typed properties: Always initialize in constructor or with a default value.
- Readonly properties in inheritance: A readonly property can be redeclared in a child class only if it's not already initialized. Use readonly classes to avoid issues.
- Property hooks performance: Hooks add a small overhead. For hot paths, consider using methods.
- Type widening: You cannot widen a property type in a subclass (e.g., from int to int|string).
- Avoid side effects in get hooks: They should be idempotent and not modify state.
Example: A common mistake – forgetting to initialize a typed property.
public function __construct(public readonly string $name) {}The Silent Data Corruption: A Typed Property Nightmare
amount property was untyped, allowing a string ' -50 ' to be stored and later used in calculations without proper casting.public float $amount; and added a setter hook (in PHP 8.4) to sanitize input.- Always use typed properties for domain-critical data.
- Never trust external input; enforce types at the boundary.
- Use readonly for values that should never change after construction.
- Property hooks can centralize validation logic.
set or get hooks. Check for typos in hook names.var_dump($value);echo gettype($value);| File | Command / Code | Purpose |
|---|---|---|
| typed_properties.php | class User { | Typed Properties |
| nullable_union.php | class Product { | Nullable and Union Types |
| readonly_properties.php | class AppConfig { | Readonly Properties |
| property_hooks.php | class User { | Property Hooks |
| combined.php | class Event { | Combining Typed, Readonly, and Hooks |
| pitfall.php | class User { | Common Pitfalls and Best Practices |
Key takeaways
Common mistakes to avoid
3 patternsAccessing an uninitialized typed property
Trying to modify a readonly property outside constructor
Using property hooks for complex business logic
Interview Questions on This Topic
What is the purpose of typed properties in PHP?
Frequently Asked Questions
20+ years shipping production PHP systems at scale. Written from production experience, not tutorials.
That's Advanced PHP. Mark it forged?
3 min read · try the examples if you haven't