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

Iterable Functions Laravel Package

bentools/iterable-functions

Small PHP utility package offering array-like helpers for any iterable (arrays, Traversable, generators): iterable_to_array/to_traversable, map, merge, reduce, filter, values, and chunk—write iterable-agnostic code without TypeError surprises.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require bentools/iterable-functions:^2.0
    

    Add the namespace to your composer.json aliases (optional but recommended for cleaner imports):

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "BenTools\\": "vendor/bentools/iterable-functions/src"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case: Convert an unknown iterable (array, generator, or Traversable) to an array safely in a Laravel service:

    use function BenTools\IterableFunctions\iterable_to_array;
    
    public function processData($data): array
    {
        // Works for arrays, generators, or ArrayIterator
        return iterable_to_array($data);
    }
    
  3. Key Entry Points:

    • Fluent Interface: Chain operations like iterable($data)->filter()->map()->asArray().
    • Type-Agnostic Functions: Use iterable_map(), iterable_filter(), etc., instead of array_* functions when working with mixed iterables.

Implementation Patterns

Workflows in Laravel

1. Normalizing Inputs

  • Use Case: API requests, form submissions, or database results may return arrays, generators, or Traversable objects.
  • Pattern:
    use function BenTools\IterableFunctions\iterable_to_array;
    
    public function store(Request $request)
    {
        $data = $request->input('items'); // Could be array or Traversable
        $processed = iterable_to_array($data); // Guaranteed array
        // Proceed with Eloquent or validation
    }
    

2. Lazy Processing for Large Datasets

  • Use Case: Batch processing CSV imports, paginated API responses, or queue jobs.
  • Pattern:
    use function BenTools\IterableFunctions\iterable_chunk;
    
    public function importCsv(UploadedFile $file)
    {
        $handle = fopen($file->path(), 'r');
        $generator = function () use ($handle) {
            while (($row = fgetcsv($handle)) !== false) {
                yield $row;
            }
        };
    
        foreach (iterable_chunk($generator(), 1000) as $batch) {
            Model::insert($batch); // Process in chunks
        }
    }
    

3. Fluent Interface for Eloquent Results

  • Use Case: Transform query results before returning to API clients.
  • Pattern:
    use function BenTools\IterableFunctions\iterable;
    
    public function getFilteredUsers()
    {
        return iterable(User::query()->get())
            ->filter(fn(User $user) => $user->isActive())
            ->map(fn(User $user) => $user->toArray())
            ->asArray();
    }
    

4. Merging Mixed Iterables

  • Use Case: Combine results from multiple API calls or database queries.
  • Pattern:
    use function BenTools\IterableFunctions\iterable_merge;
    
    public function mergeData()
    {
        $users = User::query()->get();
        $posts = Post::query()->limit(10)->get();
    
        return iterable_merge($users, $posts)
            ->map(fn($item) => $item->toArray())
            ->asArray();
    }
    

5. Type-Hinting with Traversable

  • Use Case: Accept any iterable in service methods while keeping type safety.
  • Pattern:
    use function BenTools\IterableFunctions\iterable_to_traversable;
    
    public function process(Traversable $items)
    {
        $traversable = iterable_to_traversable($items);
        // Now $traversable is guaranteed to be Traversable (ArrayIterator if input was array)
    }
    

Integration Tips

  1. Laravel Service Providers: Add helper functions to the App facade for global access:

    // app/Providers/AppServiceProvider.php
    public function boot()
    {
        if (! function_exists('iterable_to_array')) {
            require __DIR__.'/../../vendor/bentools/iterable-functions/src/functions.php';
        }
    }
    
  2. Testing: Use the fluent interface to mock iterables in PHPUnit:

    $mockIterable = iterable([1, 2, 3])
        ->filter(fn($value) => $value > 1)
        ->map('strval');
    
  3. Performance: Prefer generators (fn() => yield) over arrays for large datasets to avoid memory spikes. Example:

    $generator = fn() => yield from Model::query()->cursor();
    foreach (iterable_chunk($generator(), 50) as $batch) {
        // Process batch
    }
    
  4. API Responses: Normalize responses to arrays for consistency:

    return Response::json(iterable_to_array($data));
    

Gotchas and Tips

Pitfalls

  1. iterable_to_array() vs iterator_to_array():

    • Gotcha: iterator_to_array() throws a TypeError if passed an array. Always use iterable_to_array() for mixed iterables.
    • Fix: Replace all iterator_to_array($var) with iterable_to_array($var).
  2. Fluent Interface Memory Leaks:

    • Gotcha: Chaining methods like iterable($data)->filter()->map() creates intermediate Traversable objects, which can consume memory if not consumed (e.g., with foreach or asArray()).
    • Fix: Always call asArray() or iterate over the result to trigger evaluation:
      $result = iterable($data)->filter()->map()->asArray(); // Forces evaluation
      
  3. Generator Exhaustion:

    • Gotcha: Generators can only be iterated over once. Reusing a generator after iteration will yield nothing.
    • Fix: Recreate the generator or convert to an array if reuse is needed:
      $generator = fn() => yield 1;
      $array = iterable_to_array($generator()); // Store as array for reuse
      
  4. Key Preservation:

    • Gotcha: iterable_values() reindexes keys like array_values(). If you need to preserve keys, avoid this function.
    • Fix: Use iterable_to_array($iterable, false) to skip key reindexing.
  5. PHP 8.1+ Features:

    • Gotcha: Some functions (e.g., iterable_chunk()) may behave differently with PHP 8.1’s new features (e.g., first-class callable syntax).
    • Fix: Test with your PHP version. Example:
      // PHP 8.1: Use arrow functions
      iterable($data)->filter(fn($item) => $item > 0);
      

Debugging Tips

  1. Check Iterable Type: Use var_dump() or get_debug_type() to inspect iterables:

    $data = ['a', 'b'];
    var_dump(get_debug_type($data)); // string(4) "array"
    
  2. Lazy Evaluation Debugging: Add foreach loops to force evaluation and debug intermediate steps:

    $result = iterable($data)
        ->filter(fn($item) => $item > 0)
        ->map('strval');
    foreach ($result as $item) { // Force evaluation
        var_dump($item);
    }
    
  3. Type Errors: If you get TypeError: iterable_to_array(): Argument must be of type iterable, ensure your input is actually iterable:

    if (! is_iterable($data)) {
        throw new InvalidArgumentException('Input must be iterable');
    }
    

Extension Points

  1. Custom Filter/Map Functions: Extend the fluent interface by creating wrapper classes:

    class CustomIterable extends \BenTools\IterableFunctions\Iterable
    {
        public function customMethod()
        {
            return $this->map(fn($item) => strtoupper($item));
        }
    }
    
  2. Integration with Laravel Collections: Add a macro to Laravel’s Collection class:

    // app/Providers/AppServiceProvider.php
    public function boot()
    {
        \Illuminate\Support\Collection::macro('asIterable', function () {
            return iterable($this->all());
        });
    }
    
  3. Custom Iterators: Use iterable_to_traversable() to wrap custom iterators:

    $customIterator = new class implements \Iterator {
        // ... iterator implementation
    };
    $traversable = iterable_to_traversable($customIterator);
    
  4. Performance Profiling: Compare native functions vs. iterable functions for critical paths:

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.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views