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

Iter Laravel Package

php-standard-library/iter

Inspect and reduce any PHP iterable (arrays, generators, iterators) with small, focused helpers from PHP Standard Library - Iter. Designed for common iteration tasks and consistent behavior across iterable types.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require php-standard-library/iter
    

    No configuration or service provider setup is required—use the iter() helper globally.

  2. First Use Case: Replace a simple foreach loop with a declarative pipeline:

    // Before (imperative)
    $names = [];
    foreach ($users as $user) {
        if ($user->isActive()) {
            $names[] = $user->name;
        }
    }
    
    // After (declarative)
    $names = iter($users)
        ->filter(fn($user) => $user->isActive())
        ->map(fn($user) => $user->name)
        ->toArray();
    
  3. Key Entry Points:

    • iter($iterable): Convert any iterable (array, generator, Traversable) into an Iter object.
    • Core Methods: map(), filter(), reduce(), chunk(), flatten(), tap().
    • Terminal Methods: toArray(), first(), all(), count().
  4. Where to Look First:

    • Package Documentation for method signatures and examples.
    • Source Code for edge-case behavior (e.g., generator handling).
    • Laravel-specific examples in the Implementation Patterns section below.

Implementation Patterns

Core Workflows

1. Lazy Data Processing (Memory Efficiency)

Use Case: Process large datasets (e.g., database exports, file streams) without loading everything into memory.

// Eloquent cursor + lazy filtering (no N+1 queries)
$activeUsers = iter(User::cursor())
    ->filter(fn($user) => $user->isActive())
    ->map(fn($user) => $user->email)
    ->toArray();

// File stream processing
$lines = iter(fopen('large.csv', 'r'));
$processed = iter($lines)
    ->map(fn($line) => strtolower(trim($line)))
    ->filter(fn($line) => strlen($line) > 0)
    ->toArray();

2. Composable Pipelines

Use Case: Chain transformations (e.g., API response normalization, ETL pipelines).

// API Resource transformation
$posts = iter($rawData)
    ->map(fn($post) => [
        'id' => $post['id'],
        'title' => ucfirst($post['title']),
        'author' => $post['user']['name'],
    ])
    ->filter(fn($post) => $post['title'] !== 'Draft')
    ->sort(fn($a, $b) => strcmp($b['title'], $a['title']))
    ->chunk(10);

3. Generator Integration

Use Case: Work with Laravel’s generators (e.g., Model::cursor(), file handles, custom iterators).

// Custom generator
function generateLargeData() {
    for ($i = 0; $i < 1_000_000; $i++) {
        yield $i;
    }
}

// Process without memory overload
$sum = iter(generateLargeData())
    ->filter(fn($n) => $n % 2 === 0)
    ->reduce(fn($carry, $n) => $carry + $n, 0);

4. Batch Processing for Queues/Jobs

Use Case: Dispatch Laravel jobs in chunks to avoid memory issues.

iter(User::cursor())
    ->chunk(50)
    ->each(fn($chunk) => ProcessUsersJob::dispatch($chunk));

5. Debugging with tap()

Use Case: Inspect intermediate states in pipelines (e.g., logging, validation).

iter($users)
    ->tap(fn($iter) => Log::debug('Users loaded:', $iter->count()))
    ->filter(fn($user) => $user->isActive())
    ->tap(fn($iter) => Log::debug('Active users:', $iter->toArray()))
    ->map(fn($user) => $user->name);

Laravel-Specific Patterns

1. Eloquent Integration

  • Lazy Loading: Use cursor() with iter() to avoid eager loading.
    $activeUserIds = iter(User::where('active', true)->cursor())
        ->pluck('id')
        ->toArray();
    
  • Relationship Filtering:
    $postsWithComments = iter(Post::with('comments')->cursor())
        ->filter(fn($post) => $post->comments->count() > 0)
        ->toArray();
    

2. API Resources

  • Normalize Nested Data:
    $resource = new PostResource(
        iter($posts)
            ->map(fn($post) => [
                'id' => $post->id,
                'title' => $post->title,
                'comments' => iter($post->comments)->pluck('body')->toArray(),
            ])
            ->toArray()
    );
    

3. Blade Views

  • Conditional Rendering:
    @foreach(iter($items)->filter(fn($item) => $item->isVisible()))
        <div>{{ $item->name }}</div>
    @endforeach
    
  • Chunked Pagination:
    @foreach(iter($items)->chunk(3) as $chunk)
        <div class="row">
            @foreach($chunk as $item)
                <div>{{ $item->name }}</div>
            @endforeach
        </div>
    @endforeach
    

4. Artisan Commands

  • Stream Processing:
    public function handle() {
        iter(Storage::files('large-directory'))
            ->filter(fn($path) => str_ends_with($path, '.log'))
            ->each(fn($path) => $this->processLog($path));
    }
    

5. Testing

  • Mock Generators:
    $mockGenerator = iter([new User(), new User()]);
    $names = iter($mockGenerator)->map(fn($u) => $u->name)->toArray();
    $this->assertEquals(['Alice', 'Bob'], $names);
    
  • Validate Pipelines:
    $iter = iter([1, 2, 3]);
    $this->assertEquals([2, 4, 6], iter($iter)->map(fn($n) => $n * 2)->toArray());
    

Integration Tips

  1. Avoid Premature Materialization:

    • Use toArray() or all() only when needed. Keep pipelines lazy until the final step.
    • Example: iter($generator)->map(...)->filter(...) (still lazy) vs. iter($generator)->map(...)->toArray() (materialized).
  2. Leverage PHP 8.1+ Features:

    • Use named arguments for clarity:
      iter($users)->filter(fn($user) => $user->isActive(), true); // $strict = true
      
    • Combine with match expressions:
      $status = match($user->role) {
          'admin' => 'active',
          default => 'inactive',
      };
      
  3. Hybrid with Laravel Collections:

    • Convert to/from Collection when needed:
      $collection = iter($array)->map(...)->toCollection();
      $array = iter($collection)->toArray();
      
  4. Custom Iterators:

    • Extend functionality for domain-specific needs:
      iter($customIterator)->map(fn($item) => $item->transform());
      
  5. Error Handling:

    • Use try-catch for pipeline failures:
      try {
          $result = iter($data)->map(fn($x) => $x->invalid())->toArray();
      } catch (Error $e) {
          Log::error('Pipeline failed:', ['error' => $e->getMessage()]);
      }
      

Gotchas and Tips

Pitfalls

  1. Generator Exhaustion:

    • Generators can only be iterated once. Recreate or store results if needed:
      // ❌ Fails on second iteration
      $gen = generateData();
      iter($gen)->toArray(); // Works
      iter($gen)->toArray(); // Empty (exhausted)
      
      // ✅ Recreate generator
      $gen = generateData();
      $first = iter($gen)->toArray();
      $gen = generateData(); // Reset
      $second = iter($gen)->toArray();
      
  2. Strict Typing Quirks:

    • filter() uses loose comparison (==) by default. Use $strict = true for strict checks:
      iter([0, '0', 1])->filter(fn($x) => $x === 0, true);
      
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi