doctrine/collections
Doctrine Collections provides a lightweight, flexible collection abstraction for PHP. It offers ArrayCollection and collection interfaces with rich filtering, mapping, matching, and criteria-based querying, useful as a foundation for domain models and ORM-friendly data handling.
Install via Composer:
composer require doctrine/collections
Replace native PHP arrays with ArrayCollection for type safety and utility methods:
use Doctrine\Common\Collections\ArrayCollection;
$users = new ArrayCollection(['Alice', 'Bob', 'Charlie']);
// Basic operations
$users->add('Dave');
$users->remove('Bob');
$firstUser = $users->first();
$filtered = $users->filter(fn($user) => strlen($user) > 3);
ArrayCollection – Core collection class with rich methodsCriteria – For complex filtering/sortingExpressionBuilder – Fluent query builder for CriteriaCollection/ReadableCollection – Abstract base classesuse Doctrine\Common\Collections\ArrayCollection;
class User {
private ArrayCollection $roles;
}
$user = new User();
$user->roles = new ArrayCollection(['admin', 'user']); // Type-safe
use Doctrine\Common\Collections\Criteria;
$criteria = new Criteria();
$criteria->where(Criteria::expr()->gt('age', 25))
->orderBy(['name' => Criteria::ASC]);
$adults = $users->matching($criteria);
LazyCollectionuse Doctrine\Common\Collections\LazyCollection;
$lazyUsers = LazyCollection::fromCallback(function() {
return User::query()->fetchAll();
});
foreach ($lazyUsers as $user) { // Loads on-demand
// ...
}
use Doctrine\Common\Collections\ReadableCollection;
$immutable = new ReadableCollection(['a', 'b', 'c']);
// $immutable->add('d'); // Throws \LogicException
use Doctrine\Common\Collections\ArrayCollection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
$eloquent = new EloquentCollection([$user1, $user2]);
$doctrine = new ArrayCollection($eloquent->all());
// Convert back
$eloquent->replace($doctrine->toArray());
use Doctrine\Common\Collections\AbstractCollection;
class TagCollection extends AbstractCollection {
public function addTag(string $tag): void {
$this->add($tag);
}
}
use Doctrine\Common\Collections\Criteria;
$criteria = new Criteria();
$criteria->setMaxResults(10);
$criteria->orderBy(['created_at' => Criteria::DESC]);
return response()->json($users->matching($criteria)->toArray());
Criteria::expr() Deprecation
ExpressionBuilder for new code:
$expr = Criteria::create()->expression();
$expr->gt('age', 25); // Old
$expr = Criteria::expr()->gt('age', 25); // New (3.1+)
Key Preservation
ArrayCollection preserves array keys. Use ->toArray() to reset:
$coll = new ArrayCollection(['a' => 1, 'b' => 2]);
$coll->add('c'); // Key 'c' is lost unless explicitly set
LazyCollection Pitfalls
count() until loaded: Use LazyCollection::count() carefully.fromCallback() have access to dependencies.Type Safety
string|int) may cause runtime errors.Criteria Debugging
$criteria->where(Criteria::expr()->eq('status', 'active'));
dump($criteria->getWhereExpressionString()); // Inspect raw SQL-like logic
Collection Dumping
dump($collection->getIterator()->getArrayCopy()); // Force materialization
Custom Criteria Functions
use Doctrine\Common\Collections\Criteria;
Criteria::create()
->addCustomExpression('is_active', function($field, $value) {
return "$field = :val AND $field->isActive()";
}, ['val' => true]);
Override ArrayCollection Methods
class CustomCollection extends ArrayCollection {
public function customMethod(): void {
$this->filter(fn($item) => /* ... */);
}
}
Serialization
$collection->willInitializeObjectClosure = function() {
return new ArrayCollection(['default' => 'value']);
};
Avoid toArray() in Loops
getIterator() or getValues() for memory efficiency.Criteria Optimization
$criteria->setMaxResults(100); // Limit results early
$criteria->orderBy(['id' => Criteria::DESC]); // Sort before filtering
Lazy Loading
LazyCollection for large datasets:
$lazy = LazyCollection::fromCallback(fn() => User::all());
Service Container Binding
$this->app->bind(ArrayCollection::class, function() {
return new ArrayCollection();
});
Eloquent Relationships
hasMany with Collection:
public function posts(): HasMany {
return $this->hasMany(Post::class)->setCollectionClass(ArrayCollection::class);
}
API Resource Collections
use Doctrine\Common\Collections\Criteria;
public function toArray($request) {
$criteria = new Criteria();
$criteria->where(Criteria::expr()->eq('active', true));
return $this->collection->matching($criteria)->toArray();
}
How can I help you explore Laravel packages today?