yoshi2889/collections
A lightweight PHP collection library offering a fluent, chainable API for mapping, filtering, reducing, and transforming data. It brings expressive array manipulation to standalone PHP projects and Laravel apps alike, helping keep code concise, readable, and easy to maintain.
composer require yoshi2889/collections:^0.2. Because this is a 0.x release line, prefer pinning the minor (^0.2) and reviewing the changelog before bumping.CHANGELOG for the 0.1.6 → 0.2 diff.array + a docblock nobody enforces, return the package's collection annotated with the item type. That is the whole point of v0.2 — the new @template parameter is what lets PHPStan/Psalm understand Collection<OrderDto> rather than Collection<mixed>.Annotate at the boundary, not everywhere. The highest-value place to introduce the type parameter is where data crosses a layer: repository → service, service → controller, job → handler. Converting a raw array to Collection<OrderDto> at the edge means every downstream map/filter callback is inferred and you stop writing defensive instanceof checks.
Wrap Eloquent, don't replace it. Keep Illuminate\Support\Collection at the framework edges (controllers, resources, Blade) and use this package for the domain-shaped lists in between. A typical flow: Model::query()->get() → ->map(fn ($m) => OrderDto::fromModel($m)) → hydrate the typed collection → hand it to your domain service. Convert back to a plain array or an Illuminate collection before returning from the controller.
Subclass for domain collections. Declare a small class per aggregate (e.g. OrderCollection) with a @extends Collection<Order> style annotation and put genuinely domain-specific operations on it. This keeps call sites readable, gives you one place to enforce invariants, and means the template annotation is written once rather than at forty call sites.
Treat static analysis as the feature. The type parameter only pays off if PHPStan/Psalm runs in CI at a level where generics are actually checked. Add the package's own quality config as a reference point — v0.2 ships quality tooling upstream, so mirroring their analyser level locally is a cheap way to catch the cases where your annotations lie.
Test the collection, not just the callers. Assert on the returned values and, where it matters, that ordering and key preservation behave as you expect — collections that silently reindex or reorder are a classic source of "works in unit tests, breaks in prod" bugs.
Migration path from 0.1.x. This is a drop-in for runtime behaviour; the changes are static-analysis surface plus tooling. Bump, run the analyser, and expect a burst of new findings rather than new exceptions.
mixed or untyped will now be checked against a concrete item type. Budget for a round of annotation fixes, or baseline the errors temporarily and burn them down. This is the single most likely source of "the upgrade broke CI".Illuminate\Support\Collection. In files that touch both, alias one of them (use Yoshi2889\Collections\Collection as TypedCollection;). Silent confusion between the two in a large codebase is worse than the extra import line.macro, when, dd, toResource, higher-order proxies, and the Arr/Str conveniences are Illuminate's, not this package's. If your team's muscle memory is Laravel collections, either keep the typed collection short-lived or document the missing methods.collect() returns Illuminate. There is no global helper here. Conversion is explicit — that is a feature, but it does mean every boundary needs a one-liner and reviewers will flag inconsistency if you do it ad hoc.unserialize/json_decode lose their annotation silently — re-validate on the way in.0.x semver. A minor bump may legitimately break you. Pin the constraint, read the release notes, and don't let a composer update in CI be your upgrade strategy.How can I help you explore Laravel packages today?