← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Null Safety — Null Object vs Optional

Code Quality PHP 7.1+ Intermediate
debt(d5/e3/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpstan and psalm — both specialist static analysis tools. The code_pattern notes PHPStan below level 6 misses null analysis, meaning even with these tools the default config may not catch it; you need level 7+ as stated in quick_fix. This sits squarely at d5: not caught by compiler or default linter, but caught by specialist SAST tools when properly configured.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is enabling PHPStan at level 7+ — a configuration change — but common_mistakes reveal that remediating flagged issues involves replacing null returns with exceptions or null objects, adding nullable markers to parameters, and introducing nullsafe operators. This is a repeated small-refactor pattern across a codebase rather than a single one-line patch, landing at e3.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). The applies_to covers web, cli, and queue-worker contexts — essentially the full PHP application surface. Null safety decisions (whether to use nullable types, null objects, or exceptions) shape every method signature and return type across all contexts, creating an ongoing productivity tax as developers must reason about nullability in every component. Not quite b7 (strong gravitational pull) but broader than a single component.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap' (t5). The misconception field explicitly states that nullable types (?) 'just allow null — they do not improve safety,' which is a documented gotcha: developers commonly believe that adding ? to a type declaration is sufficient to handle null safely, when in reality it merely makes the contract explicit and still requires callers to handle null. This is a well-known, documented pitfall that most PHP developers learn eventually, matching the t5 anchor.

About DEBT scoring →

Also Known As

null safety nullable types null pointer prevention

TL;DR

Strategies for eliminating null reference errors: the Null Object Pattern provides a safe default; Optional-style wrapping makes nullability explicit.

Explanation

Tony Hoare called null his 'billion-dollar mistake'. Two design patterns address it. The Null Object Pattern provides a do-nothing implementation of an interface in place of null — a NullLogger that discards messages means callers never need to null-check the logger. The Optional/Maybe pattern (from functional languages) wraps a potentially-absent value in a container with explicit handling paths — either return a nullable type with the ?Type hint and null coalescing, or use a Result/Option type from a library. In PHP, strict nullable type declarations (?string), the nullsafe operator (?->), and null coalescing (??) are the language-native tools. PHPStan and Psalm track nullability through the code graph and flag unguarded dereferences.

Common Misconception

Nullable types (?) just allow null — they do not improve safety. Declaring ?string forces callers and implementors to acknowledge nullability explicitly. Combined with union types and match expressions, nullable types push null handling to type-checked boundaries rather than runtime crashes.

Why It Matters

Null values are the source of a huge proportion of runtime errors — explicit nullability declarations and null-safe operators make null-handling visible in the type system rather than discovered at runtime.

Common Mistakes

  • Returning null from methods that could return a typed value — use exceptions or a null object instead.
  • Not marking parameters as nullable (?Type) when null is a valid input — callers cannot see the contract.
  • Not using the nullsafe operator (?->) when chaining through potentially null objects.
  • Forgetting that JSON decode of a missing key returns null and then using the value without a null check.

Code Examples

✗ Vulnerable
// Null reference — classic cause of unexpected errors
$user = User::find($id); // may be null
echo $user->name;        // TypeError if user not found
✓ Fixed
// Option 1 — null coalescing and safe navigation
$name = User::find($id)?->name ?? 'Guest';

// Option 2 — null object pattern
class GuestUser extends User {
    public string $name = 'Guest';
    public function isGuest(): bool { return true; }
}
$user = User::find($id) ?? new GuestUser();
echo $user->name; // always safe

// Option 3 — fail fast with findOrFail
$user = User::findOrFail($id); // throws ModelNotFoundException — explicit

// PHP 8+ strict types + union types:
function findUser(int $id): User|null { return User::find($id); }
if (!$user = findUser($id)) return response('Not found', 404);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 59
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 2 pings T 0 pings W 0 pings T 2 pings F 0 pings S 1 ping S 1 ping M 0 pings T 2 pings W 0 pings T 0 pings F 0 pings S 2 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Scrapy 8 Amazonbot 7 Perplexity 5 Ahrefs 5 Unknown AI 4 ChatGPT 4 PetalBot 4 SEMrush 3 Google 1 Bing 1 Meta AI 1 Twitter/X 1 Brave Search 1 Applebot 1
crawler 42 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Enable PHPStan's strictNullChecks equivalent at level 7+ — it tracks null values through your code and flags every potential null dereference before it becomes a runtime TypeError
📦 Applies To
PHP 7.1+ web cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
Method called on potentially-null return value; array access on nullable; PHPStan below level 6 missing null analysis
Auto-detectable: ✓ Yes phpstan psalm
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update


✓ schema.org compliant