Nullsafe Operator (?->)
debt(d5/e1/b1/t5)
Closest to 'specialist tool catches it' (d5). The detection_hints list rector, phpstan, and php-cs-fixer — all specialist static analysis or refactoring tools. The pattern (nested ternary null checks in PHP 8.0+ code) is not caught by the compiler or default linter, but phpstan/rector can flag old-style null checks that should be ?-> and also detect misuse (e.g., using ?-> on non-nullable types).
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is a direct one-line substitution: replace $user !== null ? $user->getAddress() : null with $user?->getAddress(). Rector can automate this mechanically. There is no refactor needed beyond the substitution itself.
Closest to 'minimal commitment' (b1). The nullsafe operator is a syntax-level choice affecting individual expressions. It applies to web, cli, and queue-worker contexts but imposes no structural weight on future maintainers — it is a localised, self-contained syntactic decision with no gravitational pull on the broader codebase.
Closest to 'notable trap' (t5). The misconception field identifies that developers confuse ?-> with isset(): isset() checks for null and undefined, while ?-> short-circuits the chain on the first null but does not check for undefined variables. Additionally, a common_mistake notes that method arguments are evaluated before the null check, so side effects in arguments are not short-circuited — a documented gotcha most developers encounter when they first use chaining.
Also Known As
TL;DR
Explanation
Introduced in PHP 8.0, the nullsafe operator ?-> short-circuits a method/property chain when it encounters null, returning null rather than throwing an Error. This eliminates deeply nested isset() / !== null guards for fluent interfaces. For example, $user?->getProfile()?->getAvatar()?->getUrl() returns null if any step is null. It is not a substitute for proper null handling in all cases — side-effect-producing methods in a chain may not execute if a preceding step returns null.
Common Misconception
Why It Matters
Common Mistakes
- Using ?-> on objects that should never be null — hides bugs that should throw.
- Expecting ?-> to short-circuit side effects in method arguments — arguments are evaluated before the null check.
- Not using it consistently — mixing isset() checks and ?-> in the same codebase for the same pattern.
- Using it with property access but forgetting it works for method calls too — both are supported.
Code Examples
// Without nullsafe — verbose:
$country = null;
if ($user !== null) {
$profile = $user->getProfile();
if ($profile !== null) $country = $profile->getCountry();
}
// With nullsafe operator:
$country = $user?->getProfile()?->getCountry();
// Before PHP 8.0 — tedious null guards
$city = null;
if ($user !== null) {
$address = $user->getAddress();
if ($address !== null) {
$city = $address->getCity();
}
}
// PHP 8.0+ nullsafe operator — short-circuits on null
$city = $user?->getAddress()?->getCity();
// Works with method chains and property access
$countryCode = $order?->getCustomer()?->getAddress()?->getCountry()?->getIsoCode();