php-standard-library/option
Option type for PHP with Some/None to replace nullable values with explicit presence semantics. Helps avoid null checks, clarifies intent, and models optional data safely. Part of PHP Standard Library; see docs and contributing links.
Option type (inspired by functional programming) enforces explicit handling of "presence" (Some/None) vs. PHP’s implicit null checks. This aligns well with:
User::findByEmail() → Option<User>).map, filter, flatMap) over mutable state.NullPointerException-like bugs in PHP (e.g., if ($user->address->city) vs. $user->address->city->map(...)).null is sufficient).User::find(1) → Option::fromNullable($user)).Collection via map/filter methods.Option::class => fn() => new Option(...)).null for Some cases (due to object wrapping).null with Option requires exhaustive refactoring of return types and method signatures.function getUser(): ?User → function getUser(): Option<User>.Option usage.Option methods (vs. native PHP).Option assertions (e.g., assertTrue($option->isSome())).User/Order)?null) coexist with new Option-returning methods?Option, Scala’s Either)?null + @phpstan-ignore or nullable type hints suffice for the use case?Options) be validated?spatie/array-to-object or league/pipe).User::address->city) may conflict with Option chaining (e.g., $user->address()->city()).null and Option.Option types where null was previously allowed.Order entity) and refactor all nullable fields to Option.// Before
public function getShippingAddress(): ?Address { ... }
// After
public function getShippingAddress(): Option { return Option::fromNullable($address); }
Option methods (map, filter).Option for all nullable returns.null and Option (e.g., Option::fromNullable($legacyResult)).Option-aware assertions (e.g., assertSame(Some::create($value), $option)).null-returning methods in favor of Option.Option usage.Option::fromNullable($model) for query results.nullable rules to Option handling in controllers.@if($option->isSome()) ... @endif.Option (e.g., Option::fromNullable($api->get('user'))).Option-compatible (e.g., Option<User> in job data).| Priority | Task | Dependencies |
|---|---|---|
| 1 | Define Option usage guidelines (e.g., "All DTOs must use Option") |
Team alignment |
| 2 | Refactor a single domain (e.g., Order) |
Phase 1 PoC |
| 3 | Update static analysis (PHPStan) to enforce Option |
Phase 1 results |
| 4 | Create Option-aware Blade helpers |
Frontend team |
| 5 | Deprecate null-returning methods in core services |
Phase 2 completion |
| 6 | Train team on Option patterns (workshops) |
Adoption progress |
Option makes absence explicit, reducing null bugs.Option::from($user)->map(...)->filter(...)).null checks (e.g., if ($option->isSome()) vs. if ($var !== null)).Option::map calls obscure the original null source).null handling but increases abstraction debt if overused.map vs. if).Option-specific examples (e.g., "How to handle Option in API responses").None cases (e.g., ->value() without checks).Option chains (e.g., avoiding map for simple cases).Option patterns (e.g., some()/none() constructors).None cases not handled (e.g., Option::expect() in production).Option adds ~1–2 method calls per operation (minimal overhead).Some cases (object vs. null), but negligible at scale.| Scenario | Risk | Mitigation |
|---|---|---|
Unhandled None |
Silent failures (e.g., ->value() on None) |
Enforce Option::expect() in critical paths or use match() (PHP 8.0+). |
Legacy null Leakage |
Mixed null/Option logic |
Static analysis to flag inconsistent returns. |
Overuse of Option |
Cognitive overhead | Limit scope to domains where absence is meaningful. |
Third-Party null |
External APIs returning null |
Wrap all external calls in Option::fromNullable(). |
| Migration Stalls | Partial adoption breaks code | Use adapters for null ↔ Option during transition. |
How can I help you explore Laravel packages today?