A modern, immutable implementation of the Result pattern for PHP 8.3+.
Requires PHP 8.3+
- Type-safe result handling with strict type hints and PHPStan level max
- Immutable objects using PHP 8.3+
readonlyclasses - Fluent, chainable API:
map β flatMap β recover β fold - Full generic type inference via
@templateannotations - Comprehensive test suite with Pest PHP and type coverage
src/
βββ Failure.php
βββ Success.php
βββ Result.php
composer require arielespinoza07/result-patternuse ArielEspinoza07\ResultPattern\Result;
// Create results
$ok = Result::success(42);
$err = Result::failure('something went wrong');
// Wrap a throwing operation
$result = Result::attempt(fn () => riskyOperation());
// Convert nullable to Result
$result = Result::fromNullable($user, new UserNotFoundException());
// Transform and compose
$value = Result::success(2)
->map(fn ($x) => $x * 10)
->flatMap(fn ($x) => Result::success($x + 5))
->getValueOr(0); // 25
// Handle both branches
$output = $result->fold(
onSuccess: fn ($v) => "Got: {$v}",
onFailure: fn ($e) => "Error: {$e}",
);| Method | Description |
|---|---|
Result::success($value) |
Wraps a value in a Success |
Result::failure($error) |
Wraps an error in a Failure |
Result::attempt(callable, array $only = []) |
Executes a callable; catches Throwable as Failure. Pass $only to catch only specific exception types. |
Result::fromNullable($value, $error) |
null β Failure($error), non-null β Success($value) |
Result::zip(Result ...$results) |
All succeed β Success([values]), first failure wins (fail-fast) |
Result::collect(array $results) |
Processes all results; returns Failure([errors]) with every error collected (fail-all) |
| Method | Description |
|---|---|
isSuccess() |
true if Success |
isFailure() |
true if Failure |
getValue() |
Returns value (throws on Failure) β prefer getValueOr() |
getError() |
Returns error (throws on Success) β prefer getErrorOr() |
getValueOr($default) |
Safe value access with fallback |
getErrorOr($default) |
Safe error access with fallback |
toNullable() |
Success($v) β $v, Failure β null |
map(callable) |
Transform the value; no-op on Failure |
mapError(callable) |
Transform the error; no-op on Success |
flatMap(callable) |
Chain a Result-returning callable on Success |
flatMapError(callable) |
Chain a Result-returning callable on Failure |
recover(callable) |
Convert Failure β Success via fallback value |
recoverWith(callable) |
Convert Failure β Result (recovery can itself fail) |
tap(callable) |
Run a side-effect on Success without modifying the result |
onSuccess(callable) |
Run a side-effect on Success |
onFailure(callable) |
Run a side-effect on Failure |
fold(onSuccess, onFailure) |
Collapse both branches into a single value |
- Basic Success and Failure Examples
- attempt() / try() Method Examples
- zip() and collect() Examples
- fromNullable() Examples
- onSuccess and onFailure Examples
- tap() and toNullable() Examples
- Map Method Examples
- mapError() and flatMapError() Examples
- FlatMap Method Examples
- Fold Method Examples
- recover() and recoverWith() Examples
- Error Handling Examples
- PHP 8.3+
- Composer 2.0+
git clone https://github.com/ArielEspinoza07/result-pattern.git
cd result-pattern
composer installcomposer check # lint + analyse + test (all-in-one)
composer lint # check code style (Pint)
composer lint:fix # fix code style
composer analyse # static analysis (PHPStan level max)
composer test # run tests (Pest PHP)
composer test:coverage # run tests with coverage reportSee CONTRIBUTING.md for setup instructions, code conventions, and PR guidelines.