Asymmetric visibility (PHP 8.4, met in Classes and Objects) gives a property a narrower visibility for writing than for reading: public private(set) writes only inside the class, public protected(set) also in subclasses. private(set) alone implies public and makes the property final. PHP 8.5 extends the syntax to static properties.
<?php
final class Order {
public private(set) int $items = 0; // read anywhere, write inside only
public static private(set) int $placed = 0; // PHP 8.5: static properties too
public function __construct() { self::$placed++; }
public function add(int $qty): void { $this->items += $qty; }
}
$o = new Order(); $o->add(2); new Order();
echo $o->items, ' items, ', Order::$placed, " orders\n";
try { $o->items = 99; } catch (Error $e) { echo $e->getMessage(), "\n"; }
try { Order::$placed = 0; } catch (Error $e) { echo $e->getMessage(), "\n"; }Output
2 items, 2 orders Cannot modify private(set) property Order::$items from global scope Cannot modify private(set) property Order::$placed from global scope
Choose private(set) over readonly when the class must keep changing the value, as add() does, and a set hook (Subsection 4.11.7) when outside writes are allowed but must obey a rule.