doctrine/collections
Doctrine Collections is a lightweight abstraction for working with arrays and object sets in PHP. Provides Collection interfaces and implementations like ArrayCollection, plus filtering, mapping, criteria-based matching, and iteration utilities used across Doctrine projects.
Install via Composer:
composer require doctrine/collections
Replace native PHP arrays with ArrayCollection for type safety and enhanced functionality:
use Doctrine\Common\Collections\ArrayCollection;
// Initialize
$users = new ArrayCollection(['Alice', 'Bob']);
// Basic operations
$users->add('Charlie');
$users->remove('Bob');
$firstUser = $users->first();
$exists = $users->contains('Alice');
ArrayCollection: Core collection class with array-like methods.Criteria: For complex filtering (similar to Doctrine ORM queries).ExpressionBuilder: Helper for building Criteria expressions.// Before (native array)
$items = ['a', 'b', 'c'];
$filtered = array_filter($items, fn($item) => $item !== 'b');
// After (Doctrine Collections)
$collection = new ArrayCollection(['a', 'b', 'c']);
$filtered = $collection->filter(fn($item) => $item !== 'b');
Why? Type safety, fluent methods, and built-in immutability options.
use Doctrine\Common\Collections\Criteria;
// Filter users with age > 30
$criteria = Criteria::create()
->where(Criteria::expr()->gt('age', 30))
->orderBy(['name' => 'ASC']);
$activeUsers = $users->matching($criteria);
Use Case: Complex queries without SQL (e.g., filtering Eloquent collections).
LazyCollectionuse Doctrine\Common\Collections\LazyCollection;
// Load items only when accessed
$lazyUsers = new LazyCollection(
fn() => User::query()->get(),
fn($item) => $item->getId()
);
When? For large datasets or deferred execution (e.g., API pagination).
use Doctrine\Common\Collections\ImmutableArrayCollection;
// Immutable wrapper
$immutable = new ImmutableArrayCollection(['a', 'b']);
$immutable->add('c'); // Throws \LogicException
Use Case: Thread safety or functional programming patterns.
// Replace native collections in Eloquent models
protected $users = [];
public function getUsersCollection(): ArrayCollection
{
return new ArrayCollection($this->users);
}
Tip: Override newCollection() in models for consistency.
Type Safety:
ArrayCollection enforces strict typing. Mixing types (e.g., string + int) may cause issues.$collection = new ArrayCollection(['a', 'b'], 'string');
Criteria Deprecations:
Criteria::orderBy() with strings is deprecated. Use Order enum:
$criteria->orderBy(['name' => Criteria::ASC]);
use Doctrine\Common\Collections\Criteria\Order;.Lazy Loading Overhead:
LazyCollection adds a callback layer. Avoid for small datasets.getIterator() to force evaluation early.Immutable Collections:
add() throw exceptions. Use merge() for updates:
$new = $immutable->merge(['c']);
Check Types:
Use getType() or getIterator() to inspect contents:
$collection->getType(); // Returns 'string' if typed.
Criteria Debugging: Enable verbose output:
$criteria->setHydrationMode(Criteria::HYDRATE_ARRAY);
Performance:
For large collections, prefer Criteria over filter():
// Slow (PHP loop)
$collection->filter(...);
// Fast (native Criteria)
$collection->matching($criteria);
Custom Collections:
Extend ArrayCollection for domain-specific logic:
class UserCollection extends ArrayCollection
{
public function findByRole(string $role): array
{
return $this->filter(fn($user) => $user->getRole() === $role)->toArray();
}
}
Criteria Extensions: Add custom expressions:
Criteria::expr()->custom('MATCH', 'name', '%search%');
Serialization:
Implement Serializable for custom collections:
public function serialize(): string
{
return serialize($this->toArray());
}
Service Container Binding:
Bind ArrayCollection globally:
$app->bind(ArrayCollection::class, fn() => new ArrayCollection());
Form Requests: Validate collections:
$this->validate($request, [
'users' => 'array',
'users.*' => 'string|max:255',
]);
$collection = new ArrayCollection($request->users);
API Responses:
Use toArray() for JSON serialization:
return response()->json($collection->toArray());
How can I help you explore Laravel packages today?