haphpiness

These are things in PHP which make me genuinely_happy();

Asymmetric Visibility — public private(set)

PHP 8.4 lets you set different visibility for reading and writing a property. The most common pattern: publicly readable, privately writable. No more writing getters just to expose a value you don't want externally modified.

class BankAccount {
    public function __construct(
        public readonly string $holder,
        public private(set) float $balance = 0,  // Read: public. Write: private.
    ) {}

    public function deposit(float $amount): void {
        if ($amount <= 0) throw new \InvalidArgumentException('Amount must be positive');
        $this->balance += $amount;  // Private write — OK
    }
}

$account = new BankAccount('Alice', 100);
echo $account->balance;        // 100.0 — public read
$account->balance = 0;         // Error! — private write
$account->deposit(50);         // OK — internal write
echo $account->balance;        // 150.0

// Works with protected too
class Entity {
    public protected(set) int $id;           // Subclasses can write, outside can only read
    public private(set) string $createdAt;   // Only this class can write
}

Asymmetric visibility combines beautifully with property hooks and constructor promotion. Together, they give PHP one of the most expressive property systems in any language — read visibility, write visibility, get logic, set logic, and immutability, all declared inline.

Significance: Encapsulation

The getter-for-a-readable-property pattern was PHP's most common boilerplate. Asymmetric visibility eliminates it entirely: public private(set) says "anyone can read, only I can write" — exactly the intent behind most getter methods — in a single declaration.