loophp/collection
A high-performance, functional-style collection library for PHP. Provides lazy, immutable, chainable operations built on generators to map, filter, reduce, group, zip, and more. Works standalone or with Laravel, aiming for speed, memory efficiency, and fluent pipelines.
Installation
composer require loophp/collection
No configuration required—just autoload via Composer.
First Use Case
Convert an array to a Collection and chain operations:
use Loophp\Collection\Collection;
$users = ['Alice', 'Bob', 'Charlie'];
$collection = Collection::from($users);
// Basic filtering
$filtered = $collection->filter(fn($name) => strlen($name) > 3);
$filtered->all(); // ['Alice', 'Charlie']
Key Entry Points
Collection::from($array) – Convert arrays/iterables.Collection::make() – Create empty collection.$collection->all() – Get underlying array (eager evaluation).Leverage lazy operations to avoid memory spikes:
// Process 1M records without loading all at once
$largeData = Collection::from(range(1, 1_000_000));
$sum = $largeData->map(fn($x) => $x * 2)->sum(); // No intermediate array
Break logic into reusable chunks:
// User processing pipeline
$users = Collection::from($dbUsers)
->filter(fn($u) => $u['active'])
->map(fn($u) => UserModel::fromArray($u))
->groupBy(fn($u) => $u->role);
Replace Laravel’s Collection for custom logic:
// Override Laravel’s Collection in a service provider
app()->bind(Collection::class, fn() => new Loophp\Collection\Collection());
// Use in controllers
public function index()
{
return Collection::from($this->userRepository->all())
->pluck('name')
->toJson();
}
Extend for domain-specific needs:
class UserCollection extends Collection
{
public function activeOnly(): self
{
return $this->filter(fn($user) => $user->isActive());
}
}
Double Evaluation Lazy chains reset on each call. Cache intermediate results:
// ❌ Risky: Re-evaluates on each call
$filtered = $collection->filter(...);
$mapped = $filtered->map(...); // Re-filters!
// ✅ Safe: Materialize early
$filtered = $collection->filter(...)->all();
$mapped = Collection::from($filtered)->map(...);
Memory Leaks Avoid mixing lazy and eager operations:
// ❌ Memory hog: Converts to array too early
$collection->map(...)->all()->filter(...);
Laravel Collisions
If using both Collection classes, alias one:
use Loophp\Collection\Collection as LooCollection;
use Illuminate\Support\Collection as LaravelCollection;
->toArray() to debug intermediate steps.memory_get_usage() before/after operations.__toString() for debugging:
class DebugCollection extends Collection
{
public function __toString()
{
return print_r($this->all(), true);
}
}
Custom Aggregators Add domain-specific methods:
Collection::macro('avgAge', function() {
return $this->sum('age') / $this->count();
});
Lazy File Handling Stream large files without loading entirely:
$lines = Collection::from(fopen('large.csv', 'r'))
->map(fn($line) => str_getcsv($line))
->filter(fn($row) => $row[0] === 'active');
Database Integration Use with Eloquent for lazy queries:
$users = User::query()->get()->toCollection()
->filter(fn($u) => $u->posts()->count() > 0);
How can I help you explore Laravel packages today?