Weave 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

Either Or Both Laravel Package

php-standard-library/either-or-both

A three-variant disjoint union type for PHP. EitherOrBoth models values that may be present on the left, the right, or both sides at once, giving you a type-safe way to express partial successes, asymmetric results, and paired data without nullable workarounds.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require php-standard-library/either-or-both
    

    Add to composer.json under require or require-dev based on use case.

  2. First Use Case: Handling Optional Values

    use PhpStandard\EitherOrBoth\EitherOrBoth;
    
    // Create a Left-only value
    $left = EitherOrBoth::left('error_message');
    
    // Create a Right-only value
    $right = EitherOrBoth::right(['user_data']);
    
    // Create a Both value
    $both = EitherOrBoth::both('error_message', ['user_data']);
    
  3. Where to Look First


Implementation Patterns

Core Workflows

  1. Validation with Side Effects

    function validateUserInput(string $input): EitherOrBoth {
        if (empty($input)) {
            return EitherOrBoth::left('Input cannot be empty');
        }
        if (strlen($input) > 100) {
            return EitherOrBoth::both('Input too long', ['truncated' => substr($input, 0, 100)]);
        }
        return EitherOrBoth::right(['validated' => $input]);
    }
    
  2. Chaining with match()

    $result = validateUserInput($_POST['name']);
    $processed = $result->match(
        fn(string $error) => EitherOrBoth::left($error),
        fn(array $data) => EitherOrBoth::right($data),
        fn(string $error, array $data) => EitherOrBoth::both($error, $data)
    );
    
  3. Integration with Laravel

    • Form Requests: Return EitherOrBoth from rules() or authorize().
      public function rules(): array {
          return [
              'name' => ['required', 'max:100'],
          ];
      }
      
      public function withValidator($validator) {
          $validator->after(function ($validator) {
              if ($validator->errors()->any()) {
                  return EitherOrBoth::left($validator->errors()->first());
              }
              return EitherOrBoth::right(null);
          });
      }
      
  4. API Responses

    return response()->json(
        $result->match(
            fn(string $error) => ['success' => false, 'error' => $error],
            fn(array $data) => ['success' => true, 'data' => $data],
            fn(string $error, array $data) => [
                'success' => false,
                'error' => $error,
                'partial_data' => $data
            ]
        )
    );
    
  5. Service Layer Pattern

    class UserService {
        public function createUser(array $data): EitherOrBoth {
            $validation = $this->validate($data);
            return $validation->match(
                fn($error) => EitherOrBoth::left($error),
                fn($validData) => $this->save($validData),
                fn($error, $partialData) => EitherOrBoth::both($error, $partialData)
            );
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Type Safety

    • The Both variant is not a tuple or array. Use match() to extract values explicitly:
      $result->match(
          fn($left) => $left,
          fn($right) => $right,
          fn($left, $right) => [$left, $right] // Explicit pairing
      );
      
  2. Immutable Values

    • All variants are immutable. Avoid modifying the underlying values post-creation:
      // ❌ Anti-pattern: Modifying after creation
      $both = EitherOrBoth::both('error', ['data']);
      $both->getRight()['data'] = 'new_value'; // No effect!
      
  3. Null Handling

    • EitherOrBoth does not support null as a valid value. Use Option types (e.g., php-standard-library/option) for nullable cases.
  4. Performance

    • Avoid deep nesting of EitherOrBoth in loops. Prefer early returns or flat maps:
      // ❌ Inefficient
      $result = EitherOrBoth::right([]);
      foreach ($items as $item) {
          $result = $result->flatMap(fn($acc) => $this->process($item)->map(fn($v) => [...$acc, $v]));
      }
      
      // ✅ Better
      $results = collect($items)->map(fn($item) => $this->process($item));
      

Debugging Tips

  1. Inspecting Values Use match() with var_dump for debugging:

    $result->match(
        fn($left) => var_dump($left),
        fn($right) => var_dump($right),
        fn($left, $right) => var_dump([$left, $right])
    );
    
  2. Laravel Tinker Test logic interactively:

    php artisan tinker
    >>> $result = EitherOrBoth::both('error', ['data']);
    >>> $result->match(...);
    

Extension Points

  1. Custom Matchers Extend functionality with static methods:

    EitherOrBoth::match(
        $eitherOrBoth,
        fn($left) => $this->handleLeft($left),
        fn($right) => $this->handleRight($right),
        fn($left, $right) => $this->handleBoth($left, $right)
    );
    
  2. Laravel Service Provider Bind EitherOrBoth to the container for dependency injection:

    $this->app->bind(EitherOrBoth::class, function () {
        return new EitherOrBoth();
    });
    
  3. Testing Use assertSame() for strict comparisons in PHPUnit:

    $this->assertSame(
        EitherOrBoth::both('error', ['data']),
        EitherOrBoth::both('error', ['data'])
    );
    

Configuration Quirks

  • No Global Config: The package is stateless. All behavior is defined via method calls.
  • PHP Version: Requires PHP 8.1+. Use strict_types=1 for type safety.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator