private(set) on a collection, and the array copy that saves you

Exposing an array property publicly for reading felt unsafe until the copy semantics were the point rather than an accident.

final class Basket
{
    public private(set) array $lines = [];

    public function add(Line $line): void
    {
        $this->lines[] = $line;
    }
}

$copy = $basket->lines;
$copy[] = new Line();      // the basket is unchanged
$basket->lines[] = new Line();   // Error

PHP arrays are values, so reading one gives a copy and the encapsulation holds without a getter. This does not extend to an array of mutable objects — the array is copied and the objects in it are not — so a caller can still mutate a line, which is the same caveat readonly has and is worth knowing before converting a collection property.