Fetching a property on null, and where ?-> hides the bug

The nullsafe operator turns a fatal error into a null, which is sometimes exactly right and sometimes the removal of the only signal that something upstream was wrong.

$city = $order?->customer?->address?->city;

// if $order is null this is null, and so is the case where
// the customer genuinely has no address. two very different
// situations, one result.

// the version that keeps the distinction:
if ($order === null) {
    throw new OrderNotFound($id);
}

$city = $order->customer->address?->city;

The rule that has held up is one nullsafe per chain, at the link that is genuinely optional, and a real check at the links that are not. A chain of three is a statement that any of the three may legitimately be absent, which is rarely true and is usually a way of not thinking about which one. Debugging a null that came from four possible places is materially harder than a fatal error naming the exact property.