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

Fun Laravel Package

php-standard-library/fun

Functional programming utilities for PHP: compose and pipe callables, decorate functions, and control execution (memoize, throttle, debounce, retry, etc.). Part of PHP Standard Library with focused, reusable helpers for cleaner functional-style code.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require php-standard-library/fun
    

    No additional configuration is required—it’s a drop-in utility library.

  2. First Use Case: Function Composition Compose two functions into one:

    use Fun\Compose;
    
    $addFive = fn($x) => $x + 5;
    $multiplyByTwo = fn($x) => $x * 2;
    
    $composed = Compose::pipe($addFive, $multiplyByTwo);
    echo $composed(3); // Output: 16 ( (3 + 5) * 2 )
    
  3. Key Entry Points

    • Fun\Compose: For composing functions (e.g., pipe, tap).
    • Fun\Control: For flow control (e.g., try, retry).
    • Fun\Decorators: For wrapping functions (e.g., memoize, timeout).

Implementation Patterns

1. Function Composition Workflows

  • Data Transformation Pipelines Chain functions to transform data sequentially:
    $pipeline = Compose::pipe(
        fn($user) => $user->name,
        fn($name) => strtoupper($name),
        fn($name) => "Hello, {$name}"
    );
    echo $pipeline($user); // "Hello, JOHN"
    
  • Middleware-Like Decorators Use tap to inspect/intercept values mid-pipeline:
    $withLogging = Compose::pipe(
        fn($data) => $data * 2,
        fn($data) => tap($data, fn($val) => logger()->info("Value: {$val}"))
    );
    

2. Control Flow Utilities

  • Safe Execution Handle exceptions gracefully:
    $safeDivide = Control::try(fn($a, $b) => $a / $b)
        ->otherwise(fn() => 0);
    echo $safeDivide(10, 0); // 0
    
  • Retry Logic Automatically retry failed operations:
    $retryable = Control::retry(fn() => riskyOperation(), 3);
    

3. Decorator Patterns

  • Memoization Cache function results:
    $expensive = fn($input) => computeHeavyCalculation($input);
    $memoized = Decorators::memoize($expensive);
    
  • Timeouts Enforce execution limits:
    $timeout = Decorators::timeout(fn() => slowTask(), 2);
    

4. Integration with Laravel

  • Service Providers Bind composed functions to the container:
    $this->app->bind('pipeline.transform', fn() => Compose::pipe(...));
    
  • Middleware Use tap to modify requests/responses:
    $middleware = fn($request) => tap($request, fn($req) => $req->merge(['logged' => true]));
    

Gotchas and Tips

Pitfalls

  1. Closure Scope Leaks

    • Avoid capturing large objects in composed functions (e.g., $this in class methods). Use use sparingly.
    • Fix: Pass dependencies explicitly or use static closures.
  2. Memoization Pitfalls

    • memoize caches based on all arguments. Uneven argument types (e.g., array vs string) may cause unexpected misses.
    • Fix: Normalize arguments (e.g., json_encode for arrays) or use a custom cache key function.
  3. Timeout Behavior

    • timeout throws Fun\TimeoutException if the function exceeds the limit. Always wrap in a try-catch or use Control::try.
  4. Immutable Data Assumption

    • Functions like tap assume immutability. Side effects (e.g., modifying input objects) break pipelines.
    • Fix: Clone inputs if needed or use pure functions.

Debugging Tips

  • Inspect Pipelines Use Compose::tap to log intermediate values:
    $pipeline = Compose::pipe(
        fn($x) => $x + 1,
        fn($x) => tap($x, fn($v) => logger()->debug("Mid: {$v}")),
        fn($x) => $x * 2
    );
    
  • Check for Lazy Evaluation Some decorators (e.g., memoize) may not trigger computation until first use. Test with actual invocations.

Extension Points

  1. Custom Composers Extend Compose by creating static methods:
    Compose::static('batch', fn(...$fns) => fn($input) => array_reduce($fns, fn($acc, $fn) => $fn($acc), $input));
    
  2. Control Flow Strategies Override Control::retry logic (e.g., exponential backoff):
    Control::retry(fn() => $operation, 3, fn($attempt) => sleep($attempt));
    
  3. Decorator Chaining Combine decorators dynamically:
    $decorated = Decorators::chain(
        Decorators::memoize($func),
        Decorators::timeout($func, 1)
    );
    
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
milesj/emojibase
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