atournayre/collection
Type-safe PHP collections with list/map factories, plus immutable variants. Includes DecimalValue collections with consistent precision handling. Build domain-specific collections by extending TypedCollection to enforce item types and safe manipulation.
Installation:
composer require atournayre/collection
No service provider or facade needed—use it as a standalone utility.
First Use Case:
use ATournayre\Collection\Collection;
$items = ['apple', 'banana', 'cherry'];
$collection = new Collection($items);
// Basic filtering
$fruitsWithA = $collection->filter(fn($item) => str_starts_with($item, 'a'));
// Returns: ['apple']
Where to Look First:
Collection class docs (if any) or PHPDoc comments in the codebase.Illuminate\Support\Collection for comparison (similar API).Chaining Methods:
$result = $collection
->filter(fn($item) => strlen($item) > 5)
->map(fn($item) => strtoupper($item))
->sort();
Integration with Laravel:
collect() calls where custom logic is needed:
$users = User::all();
$activeAdmins = (new Collection($users))
->where('is_admin', true)
->where('active', true);
Custom Logic:
Collection class for domain-specific methods:
class UserCollection extends Collection {
public function activeAdmins() {
return $this->where('role', 'admin')->where('active', true);
}
}
Data Transformation:
transform() or map() for nested structures:
$posts = (new Collection($posts))
->map(fn($post) => [
'title' => $post->title,
'author' => $post->user->name,
]);
Performance Considerations:
each() for side-effects (avoids creating new collections):
$collection->each(fn($item) => Log::info($item));
Lazy Loading:
filter() or map() return new collections, not modified instances. Avoid chaining if memory is a concern:
// Bad: Creates 3 intermediate collections
$result = $collection->filter()->map()->sort();
Type Safety:
$collection = new Collection($items); // $items must be iterable
Laravel Collision:
use ATournayre\Collection\Collection as CustomCollection;
Undocumented Methods:
chunk(), collapse(), or flatten() (if available).pluck() (compare with Laravel’s pluck()).Inspect Collections:
$collection->dump(); // Uses Laravel’s dump() if available
// Fallback:
print_r($collection->all());
Common Errors:
InvalidArgumentException: Pass non-iterable data to the constructor.
Fix: Use array() or collect() first.forelse vs. foreach).Macros: Add reusable methods globally:
Collection::macro('firstWhereIn', function ($key, $values) {
return $this->firstWhere($key, fn($val) => in_array($val, $values));
});
Custom Comparators:
Override equals() for deep comparison:
class DeepCollection extends Collection {
public function equals($collection) {
return $this->all() === $collection->all();
}
}
Integration with Laravel Events:
Collection::macro('trigger', function ($event) {
event(new \App\Events\CollectionProcessed($this));
});
How can I help you explore Laravel packages today?