Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Result Laravel Package

php-standard-library/result

A lightweight Result type for PHP that represents success or failure as a value, enabling controlled error handling without exceptions. Helps you return, compose, and inspect outcomes explicitly for safer, predictable application flow.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Monadic/Functional Paradigm Alignment: The Result type enforces explicit error handling via Ok/Err variants, aligning well with Laravel’s growing adoption of functional patterns (e.g., collect(), tap()). This contrasts with Laravel’s traditional exception-based error handling, offering an alternative for domain-driven design (DDD) or bounded contexts where errors are part of the business logic (e.g., validation, external API responses).
  • Composability: The package’s immutability and method chaining (e.g., map(), flatMap()) integrate seamlessly with Laravel’s service containers and middleware pipelines, enabling declarative error flows (e.g., Result::fromCallable(fn() => Model::findOrFail($id))->map(...)).
  • Laravel-Specific Synergies:
    • Validation: Can replace Validator::fails() checks with Result::Err() for structured responses.
    • HTTP Responses: Maps naturally to Laravel’s Response facade (e.g., Result::match(fn($data) => response($data), fn($err) => response($err, 400))).
    • Jobs/Queues: Enables explicit error propagation in async workflows (e.g., Bus::dispatch(new ProcessOrder($order))->then(fn($result) => $result->match(...))).

Integration Feasibility

  • Low Friction: Zero dependencies (beyond PHP 8.1+) and MIT license eliminate adoption barriers. Compatible with Laravel’s autoloading (PSR-4) and container binding.
  • Backward Compatibility: Non-breaking; can coexist with existing exception-based code via adapters (e.g., Result::fromThrowable()).
  • Testing: Enhances unit testing by replacing expectException() with expect(Result::err()) assertions, improving test readability.

Technical Risk

  • Cognitive Load: Requires team buy-in to shift from exceptions to Result for certain use cases. Risk mitigated by:
    • Gradual Adoption: Start with new features or bounded contexts (e.g., API layers).
    • Tooling: Create custom PHPDoc tags (e.g., @returns Result<Model, ValidationError>) and IDE plugins to highlight Result-returning methods.
  • Performance: Minimal overhead (immutable objects), but micro-optimizations may be needed in hot paths (e.g., caching Result instances for repeated operations).
  • Laravel Ecosystem Gaps:
    • No Native Integration: Laravel’s Http/Validation components lack built-in Result support (e.g., Validator::validate() returns bool). Workaround: Wrap calls in Result::fromCallable().
    • Logging: Requires custom logging middleware to capture Err variants (e.g., Result::match(..., fn($err) => Log::error($err))).

Key Questions

  1. Use Case Prioritization:
    • Which Laravel layers (API, CLI, Jobs) would benefit most from Result?
    • Example: Replace try-catch in API controllers with Result::match() for HTTP responses.
  2. Error Granularity:
    • Should Err carry domain-specific error types (e.g., PaymentFailed) or remain generic?
  3. Migration Strategy:
    • How to handle legacy exception-based code? (e.g., Result::fromThrowable() vs. custom adapters).
  4. Tooling:
    • Can static analysis tools (PHPStan, Psalm) enforce Result usage in specific contexts?
  5. Testing Impact:
    • Will Result improve test coverage for edge cases (e.g., Result::err(new RuntimeException()))?

Integration Approach

Stack Fit

  • PHP 8.1+: Leverages named arguments and union types (Result<Model, string>) for type safety.
  • Laravel 10+: Aligns with Laravel’s functional programming trends (e.g., Illuminate\Support\LazyCollection).
  • Complementary Packages:
    • spatie/laravel-activitylog: Use Result to log failures explicitly (e.g., Result::match(..., fn($err) => Activity::log($err))).
    • fruitcake/laravel-cors: Handle CORS errors as Result::Err() for consistent responses.
    • spatie/laravel-query-builder: Replace try-catch in custom queries with Result::fromCallable().

Migration Path

  1. Phase 1: Proof of Concept (PoC)
    • Implement Result in a single feature (e.g., API endpoint for user creation).
    • Compare maintainability vs. traditional try-catch.
    • Example:
      // Before
      try {
          $user = User::create($data);
          return response($user);
      } catch (ValidationException $e) {
          return response($e->errors(), 422);
      }
      
      // After
      $result = Result::fromCallable(fn() => User::create($data));
      return $result->match(
          fn($user) => response($user),
          fn($err) => response($err->errors(), 422)
      );
      
  2. Phase 2: Domain-Specific Adoption
    • Apply Result to domains with complex error flows (e.g., payment processing, external API calls).
    • Create a base ResultAwareController trait for consistency.
  3. Phase 3: Infrastructure Layer
    • Wrap Laravel’s exception-prone methods (e.g., Cache::get(), Mail::send()) in Result adapters.
    • Example:
      Result::fromCallable(fn() => Cache::get('key'))->unwrapOrThrow();
      

Compatibility

  • Laravel Facades: Fully compatible; wrap facade calls in Result (e.g., Result::fromCallable(fn() => Auth::user())).
  • Middleware: Use Result to short-circuit requests early (e.g., Result::match($authResult, ..., fn($err) => abort(401, $err))).
  • Service Providers: Bind Result to the container for dependency injection:
    $this->app->bind(Result::class, fn() => new Result());
    

Sequencing

  1. Start with New Code: Avoid modifying legacy exception-heavy codebases initially.
  2. API Layer First: High ROI due to HTTP response consistency.
  3. Jobs/Queues: Use Result to propagate errors in async workflows (e.g., Bus::dispatch(new ProcessOrder($order))->then(fn($result) => $result->match(...))).
  4. CLI Artisan Commands: Replace throw new RuntimeException() with return Result::err(new RuntimeException()).
  5. Last: Database Layer: Use Result with Eloquent queries (e.g., Result::fromCallable(fn() => User::where(...)->first())).

Operational Impact

Maintenance

  • Pros:
    • Explicit Errors: Result forces error handling upfront, reducing runtime surprises.
    • Immutable State: Easier to debug than mutable objects with side effects.
    • Composable: Simplifies complex workflows (e.g., Result::flatMap() for sequential operations).
  • Cons:
    • Boilerplate: May increase LOC for simple operations (mitigate with helper methods).
    • Tooling Gaps: Lack of IDE support for Result types (e.g., "Show possible Err variants").
    • Migration Debt: Legacy exception-based code may require wrappers.

Support

  • Developer Onboarding:
    • Requires training on functional error handling vs. exceptions.
    • Document Result usage patterns (e.g., "Always use match() for HTTP responses").
  • Debugging:
    • Advantage: Stack traces for Err are clearer than nested try-catch.
    • Challenge: Debugging Result chains may need custom logging (e.g., Result::tap(fn($result) => Log::debug($result))).
  • Third-Party Libraries:
    • Wrap external library calls in Result (e.g., Result::fromCallable(fn() => Stripe::charges()->create($params))).

Scaling

  • Performance:
    • Minimal Overhead: Immutable objects with no runtime reflection.
    • Caching: Cache Result::Ok() for idempotent operations (e.g., Result::fromCallable(fn() => Cache::remember(...))).
  • Concurrency:
    • Async Workflows: Use Result with Laravel Queues to handle job failures explicitly (e.g., Job::handle() => Result::match(..., fn($err) => $this->fail($err))).
    • Parallel Processing: Combine with spatie/async for Result-aware parallel tasks.
  • Horizontal Scaling:
    • Result is stateless; scales identically to exception-based code.

Failure Modes

| Failure Scenario | Traditional Exception Handling | **Result-Based Handling

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4