Null Reference Errors
debt(d7/e3/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). The term's detection_hints.tools is not specified. Null reference errors in PHP are typically silent until runtime — a call to a member function on null produces a fatal error or TypeError only when that code path is executed. Static analysis tools (e.g. PHPStan, Psalm) can catch some cases but are specialist opt-in tools not universally adopted, and many null paths only manifest under specific data conditions. This lands at d7 rather than d9 because the error is at least a hard crash (not silently wrong output) once triggered.
Closest to 'simple parameterised fix' (e3). The quick_fix describes a small set of targeted changes: swap User::find() for findOrFail(), apply the nullsafe operator (?->), or add nullable return type declarations (?User). Each is a local, within-file change, but addressing the pattern across a codebase (scattered null checks vs. boundary handling) typically requires touching multiple call sites, making it slightly more than a one-liner but not a cross-cutting refactor.
Closest to 'persistent productivity tax' (b5). The misconception highlights that scattered null checks throughout business logic are a design smell that slows down many work streams — every new feature must navigate the same nullability uncertainty. The applies_to scope covers both web and cli contexts broadly. It is not as load-bearing as a shared architectural abstraction (b7) but it does impose an ongoing productivity tax across many code paths.
Closest to 'serious trap' (t7). The misconception directly states the canonical wrong belief: that defensive if ($x !== null) checks scattered everywhere are the correct approach. This contradicts good design practice — the obvious defensive move actively hides the real issue rather than fixing it. A competent developer who has used similar patterns in other languages (guard clauses, defensive checks) will naturally reach for scattered null checks and be wrong about this being the right solution in a well-structured PHP codebase.
Also Known As
TL;DR
Explanation
A null reference error occurs when code assumes a variable holds an object but it holds null instead. In PHP: $user->getName() when $user is null throws 'Call to a member function getName() on null'. Common causes: database queries that return null when no record is found (User::find($id) returns null if the user does not exist); optional relationships not loaded; functions that return null on failure without signalling this in the type signature. Solutions: null checks (if ($user !== null)); nullsafe operator (PHP 8.0+: $user?->getName()); strict return types and null coalescing ($user ?? throw new NotFoundException()); using findOrFail() in Eloquent which throws ModelNotFoundException instead of returning null. In JavaScript: optional chaining (user?.name) prevents the error. PHP 8.0's nullsafe operator (?->) chains method calls that short-circuit to null if any step is null.
Common Misconception
Why It Matters
Common Mistakes
- Using User::find($id) without checking for null — use findOrFail($id) to throw an exception, or check $user !== null before use.
- Accessing relationship properties without checking if the relationship is loaded — $post->author->name throws if author is null (no related record).
- Not declaring return types as nullable (?User) when a function can return null — the type signature should communicate nullability.
- Suppressing the error with @ instead of handling it — @$user->name silences the error but the variable is still null and the behaviour is undefined.
Code Examples
// No null check — throws on missing user
$user = User::find($id);
echo $user->getName(); // 'Call to member function on null'
// Nested null checks — verbose and easy to miss
if ($user !== null) {
if ($user->getProfile() !== null) {
echo $user->getProfile()->getAvatar();
}
}
// findOrFail throws ModelNotFoundException — handled centrally
$user = User::findOrFail($id);
echo $user->getName(); // safe — exception if not found
// PHP 8 nullsafe operator — chains short-circuit to null
echo $user?->getProfile()?->getAvatar() ?? 'default-avatar.png';
// Eloquent: fail fast at the data layer
try {
$order = Order::findOrFail($orderId);
} catch (ModelNotFoundException $e) {
return response()->json(['error' => 'Order not found'], 404);
}