Lesson 9 / 25
Property Hooks, Asymmetric Visibility, Attributes and Magic Methods
Use PHP 8.4 property features, attributes and magic methods sensibly.
The newest object features
PHP 8.4 added property hooks: get and set logic attached directly to a property, so you can validate or compute values without writing separate getter and setter methods, while callers still use plain property syntax ($product->price = 499;). It also added asymmetric visibility, such as public private(set) string $status, meaning anyone can read the property but only the class can change it, which replaces many getter-only patterns. Attributes (PHP 8.0), written #[Route('/orders', methods: ['GET'])], attach structured metadata to classes, methods, properties and parameters; frameworks read them via reflection for routing, validation, ORM mapping and dependency injection, replacing docblock annotations. Magic methods such as __get, __set, __call, __toString, __invoke and __serialize customise behaviour, but overusing __get/__call hides APIs from IDEs and static analysis; prefer explicit methods and the newer typed features. Also note PHP 8.4's ability to chain on new without extra parentheses: new Order()->addItem(...).
Property hooks and asymmetric visibility (PHP 8.4)
Validation in a set hook; status readable everywhere but writable only inside the class.
<?php
declare(strict_types=1);
final class Product
{
public private(set) string $status = 'draft'; // public read, private write
public int $pricePaise {
set (int $value) {
if ($value < 0) {
throw new InvalidArgumentException('Price cannot be negative');
}
$this->pricePaise = $value;
}
}
public string $displayPrice {
get => number_format($this->pricePaise / 100, 2) . ' INR'; // computed, no storage
}
public function __construct(public readonly string $sku, int $pricePaise)
{
$this->pricePaise = $pricePaise; // runs the set hook
}
public function publish(): void
{
$this->status = 'published';
}
}
$p = new Product('PEN-BLUE', 4950);
echo $p->displayPrice, PHP_EOL; // 49.50 INR
// $p->status = 'published'; // Error: cannot modify private(set) property
$p->publish();Check your PHP version before using new syntax
Property hooks and asymmetric visibility require PHP 8.4. Libraries that must support older versions should keep explicit getter and setter methods; applications on 8.4+ can adopt the new syntax gradually.
Quick check: What does `public private(set) string $status` mean in PHP 8.4?
- The property is private for reading and writing
- The property is constant
- Anyone can read the property, but only the class itself can modify it
- It is a syntax error
Answer
Anyone can read the property, but only the class itself can modify it — Asymmetric visibility separates read access from write access.