prewk/result
prewk/result brings Rust-like Result to PHP: explicit Ok/Err values for safer, more readable error handling without exceptions. Use map/flatMap, unwrap/unwrapOr, and chain operations to handle success and failure paths cleanly in functional style.
prewk/result package implements a Result-type pattern (success/failure) inspired by Rust’s Result<T, E>, which is a natural fit for:
map, flat_map, match).try/catch blocks) with a structured, composable alternative.Pipeline::send()->through()) for chained operations.Result<Model, ValidationException>).Result to Laravel’s Response (e.g., 200 OK for Ok, 422 Unprocessable for Err).try/catch blocks (e.g., assert Result::isOk()).spatie/laravel-validation if not adapted).php-functional/functional).| Risk Area | Mitigation Strategy |
|---|---|
| Learning Curve | Requires team buy-in for new error-handling patterns; pair with workshops. |
| Performance Overhead | Minimal (immutable objects), but benchmark in high-throughput services. |
| Debugging Complexity | Stack traces may be less intuitive than exceptions; log Result failures explicitly. |
| Migration Cost | Gradual adoption: Start with new features, avoid rewriting existing exception logic. |
| Tooling Support | IDE autocompletion (e.g., match expressions) may need configuration. |
App\Exceptions\Handler)?Result-based tests differ from exception-based tests (e.g., assertThrows vs. assertIsOk)?try/catch blocks coexist with Result types?Result be backported to older PHP/Laravel versions via polyfills?Err cases be logged/observed (e.g., Sentry, Laravel Log)?Result failures and exceptions?match expressions and named arguments.composer require prewk/result.spatie/laravel-validation to return Result<Model, ValidationErrors>.symfony/http-foundation for Result-aware responses.phpunit/phpunit for Result-specific assertions.if/else fallbacks.| Phase | Action Items | Tools/Techniques |
|---|---|---|
| Assessment | Audit codebase for expected failure points (e.g., API calls, validation). | Static analysis (PHPStan, Psalm). |
| Pilot | Implement Result in new features or low-risk modules (e.g., a validation service). |
Feature flags for gradual rollout. |
| Core Services | Refactor services/commands to return Result instead of throwing exceptions. |
IDE refactoring (PHPStorm/Rider). |
| HTTP Layer | Create middleware to convert Result to HTTP responses (e.g., ResultMiddleware). |
Laravel middleware pipeline. |
| Testing | Update tests to assert Result states (e.g., assertTrue($result->isOk())). |
PHPUnit custom matchers. |
| Monitoring | Instrument Err cases for logging/metrics (e.g., tapErr(fn($e) => Log::error($e))). |
Laravel Log, Sentry, or custom observers. |
Result::err() for hybrid approaches:
try { return Result::ok($data); } catch (\Exception $e) { return Result::err($e); }
Illuminate\Support\Result).prewk/result@2.0) may introduce breaking changes (monitor GitHub).Result to HTTP responses).PaymentResult).Result propagates correctly through dependency injection.Result and exceptions:
class ResultExceptionAdapter {
public static function toException(Result $result): void {
if ($result->isErr()) throw new RuntimeException($result->unwrapErr());
}
}
try/catch blocks in favor of flat match logic.Err cases are visible at compile time (vs. runtime exceptions).Result objects are immutable, reducing side-effect bugs.unwrap(), unwrapOr()) can be verbose.Result-specific refactoring (vs. exceptions).$result->match(
fn($data) => $data->process(),
fn($error) => Log::error($error)
);
Result::fromCallable()).Result failures are predictable and localized to specific operations.Err handling conventions (e.g., "Always log Err cases in production").Err cases (compile-time warnings with strict_types).Result and exceptions in the same code path.How can I help you explore Laravel packages today?