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.
Installation:
composer require php-standard-library/iter
No configuration required—just autoload via Composer.
First Use Case:
Replace a manual foreach loop with a lazy pipeline. For example, transform and filter an array of user IDs:
use Iter\Iter;
$userIds = [1, 2, 3, 4, 5];
$activeUsers = Iter::from($userIds)
->filter(fn($id) => $id % 2 === 0) // Keep even IDs
->map(fn($id) => "user_$id") // Prefix with "user_"
->toArray(); // Materialize to array
// Result: ["user_2", "user_4"]
Key Entry Points:
Iter::from($iterable): Wrap any iterable (array, generator, Traversable).map(), filter(), reduce(), chunk(), etc.toArray(), toGenerator(), or iterate directly.Where to Look First:
map, filter, reduce, flatMap, take, skip, chunk.Data Transformation Pipelines:
Use map/flatMap to transform data in a declarative way. Example: Flatten nested arrays and filter:
$nestedData = [[1, 2], [3, [4, 5]]];
$flattened = Iter::from($nestedData)
->flatMap(fn($item) => is_array($item) ? $item : [$item])
->filter(fn($item) => $item > 2)
->toArray();
// Result: [3, 4, 5]
Lazy Evaluation: Avoid loading all data into memory upfront. Example: Process large files line-by-line:
$lines = Iter::from($fileHandle)
->map('trim')
->filter(fn($line) => !empty($line))
->take(100); // Only process first 100 lines
Integration with Laravel:
Iter for custom logic:
$users = User::all();
$iter = Iter::from($users->toArray())
->filter(fn($user) => $user->is_active)
->map(fn($user) => $user->name);
chunk() to paginate results without cursor():
$chunked = Iter::from($query->get())
->chunk(20)
->map(fn($chunk) => $chunk->toBase());
Testing:
Mock iterables in tests by returning Iter objects with predefined sequences:
$mockIter = Iter::from([1, 2, 3])
->map(fn($i) => "item_$i");
$this->assertEquals(["item_1", "item_2"], $mockIter->take(2)->toArray());
Iter::from() to normalize mixed iterables (e.g., arrays from APIs vs. generators from DB).toGenerator() over toArray() for large datasets to avoid memory spikes.Iter in try-catch for external iterables (e.g., file handles) that might throw exceptions.Iter to the container for dependency injection:
$this->app->bind(Iter::class, fn() => new Iter());
Immutable Iterables:
map() return new Iter objects; they don’t modify the original iterable.Generator Exhaustion:
$gen = (fn() => yield 1, yield 2)();
$iter = Iter::from($gen)->toArray(); // Materialize
Lazy Evaluation Quirks:
filter()->map()) are lazy until materialized. Debugging intermediate steps requires explicit calls like toArray():
$iter = Iter::from([1, 2, 3])->filter(fn($i) => $i > 1);
// $iter still contains [1, 2, 3] until materialized!
Edge Cases with null or Non-Iterables:
Iter::from(null) throws an exception. Use empty() checks or Iter::empty() for safe defaults:
$iter = $data ? Iter::from($data) : Iter::empty();
Iter::from($iterable)->toArray() to debug intermediate states.take(1) or first() can help isolate issues in large pipelines.memory_get_usage() when working with large toArray() calls.Custom Iterables:
Implement IteratorAggregate or Generator and pass to Iter::from() for seamless integration:
class MyIterator implements IteratorAggregate {
public function getIterator() { /* ... */ }
}
$iter = Iter::from(new MyIterator());
Extension Points:
$iter->customMethod(fn($iter) => $iter->filter(...)->map(...));
Iter class for domain-specific logic (e.g., UserIter with activeOnly()).Performance Tuning:
chunk() to parallelize work:
$iter->chunk(100)->map(fn($chunk) => parallelProcess($chunk));
reduce() on large datasets; use fold() for incremental processing.Laravel-Specific:
Collection methods for hybrid pipelines:
$result = Iter::from($collection->toArray())
->map(fn($item) => $collection->firstWhere('id', $item['id']))
->filter();
Iter in Eloquent relationships to transform related data:
$user->posts()->get()->map(fn($post) => $post->title);
// Replace with:
Iter::from($user->posts)->map(fn($post) => $post->title);
How can I help you explore Laravel packages today?