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 enforces explicit presence/absence semantics, aligning with functional programming principles. This is particularly valuable in Laravel for:
User::find(999) → None) and "found but empty" (e.g., User::find(1)->address → None).Option<Payment> vs. null for failed transactions).Option::fromNullable(env('DB_HOST'))).Option enforces null safety for ORM operations (e.g., Option::fromNullable(User::find($id))).Option::fromNullable(app()->make('MissingService'))).null is sufficient, Option introduces unnecessary complexity.map/flatMap vs. if/else).Option::fromNullable($model) for query results.Collection methods (e.g., map, filter) but requires explicit Option handling.Option::class => fn() => Option::none()).null checks.Some cases (object wrapping), but insignificant at scale.Option usage (e.g., Option where null was previously allowed).Option methods (e.g., isSome(), unwrap()).null with Option requires updating all return types and method signatures (e.g., function getUser(): ?User → function getUser(): Option).null/Option logic may cause runtime errors if not handled via adapters (e.g., Option::fromNullable($legacyResult)).Option::map calls may obscure the original null source.Option assertions (e.g., assertTrue($option->isSome())).Options) need validation.Option be global (all nullable types) or targeted (specific domains like Order/User)?null-returning methods coexist with new Option-returning methods?Option, Scala’s Either)?null + @phpstan-ignore or PHP 8.1’s null attributes suffice for the use case?Options, None handling) be validated in CI/CD?spatie/array-to-object or league/pipe) or those prioritizing null safety.User::address->city) may conflict with Option chaining (e.g., $user->address()->city()).null and Option (e.g., Option::fromNullable($request->input('optional_field'))).Option types where null was previously allowed (e.g., Option instead of ?Type).Option::fromNullable($query->first())).Phase 1: Proof of Concept (2–4 weeks)
Order entity) and refactor all nullable fields to Option.?Type with Option in return types (e.g., function getShippingAddress(): Option).Option methods (map, filter, unwrap).Option-aware Blade helpers (e.g., @if($option->isSome())).null handling (e.g., fewer NullPointerException-like errors).Phase 2: Incremental Adoption (4–8 weeks)
Option for all nullable returns.null and Option (e.g., Option::fromNullable($legacyResult)).Option-aware assertions (e.g., assertSame(Some::create($value), $option)).Option usage.Option patterns (e.g., "Always handle None cases").Phase 3: Full Migration (8–12 weeks)
null-returning methods in favor of Option.Option patterns (e.g., map vs. if/else).Option into CI/CD (e.g., fail builds on unhandled None cases).Option (e.g., Option::fromNullable(User::find($id))).nullable rules to Option handling in Form Requests:
public function rules(): array {
return [
'optional_field' => ['sometimes', 'string'],
];
}
// In controller:
$value = Option::fromNullable($request->optional_field);
@if($option->isSome())
{{ $option->unwrap()->name }}
@else
<span class="text-gray">Not available</span>
@endif
Option (e.g., Option::fromNullable($api->get('user'))).Option-compatible (e.g., Option<User> in job data).Option.| Priority | Task | Dependencies | Owners |
|---|---|---|---|
| 1 | Define Option usage guidelines (e.g., "All DTOs must use Option") |
Team alignment | PM + Tech Lead |
| 2 | Refactor a single domain (e.g., Order) |
Phase 1 PoC | Backend Team |
| 3 | Update static analysis (PHPStan) to enforce Option |
Phase 1 results | QA + DevOps |
| 4 | Create Option-aware Blade helpers |
Frontend team | Frontend Lead |
| 5 | Deprecate null-returning methods in core services |
Phase 2 completion | Backend Team |
| 6 | Train team on Option patterns (workshops) |
Adoption progress | PM + Tech Lead |
| 7 | Integrate Option into CI/CD (e.g., fail on unhand |
How can I help you explore Laravel packages today?