php-standard-library/vec
Functions for creating and transforming sequential, 0-indexed arrays (lists) in PHP. Part of the PHP Standard Library, offering a consistent, functional approach to building and manipulating vec-like list structures.
Architecture fit
php-standard-library/vec is a narrow, framework-agnostic utility package: functions for creating and transforming sequential, 0-indexed arrays. It has no Laravel service provider, no facade, no config, and no Eloquent awareness — which is both its virtue (portable across Laravel, Lumen, Symfony, and plain PHP services) and its main architectural question: where does it sit relative to Illuminate\Support\Collection and native array_*?
The defensible architectural argument is a type-narrowing one. array is an overloaded type in PHP: list, map, sparse map, and tuple all share one signature. If Vec is used as a return type and parameter type in domain code (public function items(): Vec), it encodes the invariant "this is a list, keys 0..n-1" in the type system rather than in a comment, giving PHPStan/Psalm something to check. That is a real, reviewable benefit — but only if the package ships generics-annotated docblocks/stubs and immutable semantics. The README/description does not confirm generics support, immutability guarantees, or the actual method surface, so this must be verified before it is used as an architectural primitive.
Where it does not fit: Eloquent results, request payload validation, Blade rendering, and anywhere a keyed/associative structure is natural. Introducing Vec there creates a third array idiom in the codebase alongside native arrays and Collection.
Integration feasibility
Technically trivial: a composer require, autoloading via PSR-4, zero bootstrap. The realistic friction is organizational, not technical — 1 star, 0 dependents, and a split-package release history that mirrors the monorepo (6.1.x–6.3.x all point at the main repository's release notes). That means version numbers are coupled to the whole standard library, changelogs are not package-specific, and breakage diagnosis routes through a repository you don't control.
Technical risk
map, filter, reduce already exist on Collection; two implementations of the same verb in one codebase is a predictable source of review friction and inconsistent pipelines.array_values reindex, or undefined behavior? This is the single most important thing to test, because silent reindexing corrupts data in ETL-style paths.Key questions
Vec) and does it ship static-analysis stubs for generics (Vec<int, User>)?Vec an interface or a final class? Can we type-hint it without binding to the concrete implementation?Collection — is there a supported conversion path, or do we write one?Stack fit
Position Vec as a domain-layer value type for ordered data, deliberately behind the framework boundary:
| Layer | Use Vec? |
Rationale |
|---|---|---|
| Domain services, DTO transforms, batch pipelines | Yes | Immutable list semantics, composable, testable in isolation |
| Eloquent models, query builders, relationships | No | Collection is native and already keyed |
| Controllers / FormRequests | No | Stay with framework types; convert at the edge |
| Blade / API Resources | No | Avoid a third conversion hop |
The rule to publish: Vec may be a return type and a parameter type in the domain namespace; it may not cross into App\Http or App\Models.
Migration path
Collection and native array_map. Output: go/no-go memo.App\Support\Lists) wrapping conversion in both directions. If the package is later dropped, only this file changes — the domain call sites keep working.Vec/Collection chains in the same expression. If not, remove the dependency; cost was one sprint.Compatibility
No framework coupling means Laravel 10/11/12 compatibility is a PHP-version question only. Coexistence with Collection requires explicit conversion at boundaries; keep those conversions in the adapter, not scattered. Standard PHPUnit/Pest works — add a single assertVecEquals assertion helper to TestCase so failures diff on toArray() rather than on object internals.
Sequencing Install → characterization tests + benchmark → adapter → one-module pilot → ADR → optional broader adoption for new code only. Do not gate any roadmap item on this decision; it is a code-quality choice, not a delivery dependency.
Maintenance Low ongoing effort, non-trivial vendor risk. Pin to an exact version, not a caret range, while upstream is at 6.x with monorepo-coupled releases. The realistic hedge is that the package is small: a fork or a ~200-line internal replacement for the handful of functions actually used is a credible fallback and should be costed upfront (roughly 1–2 engineer-days). Assign a named internal owner; "the team" is not an owner.
Support Community-only, no commercial backing, no package-specific changelog. Escalation path is the upstream issue tracker in the monorepo. Budget zero expectation of upstream responsiveness for Laravel-specific needs — any facade or service-provider integration is ours to build, and there is no strong reason to build it.
Scaling
For request-sized payloads (hundreds to low thousands of elements) the abstraction cost is immaterial next to I/O. For hot loops, queue workers processing large batches, or memory-sensitive jobs, do not adopt without a benchmark, and prefer generators/streaming over materializing a Vec of the whole dataset. Watch for object-per-list allocation in tight loops — a Vec wrapping an array per iteration is the classic regression pattern here.
Failure modes
Collection, half uses Vec, and reviewers can't tell which is correct. Prevented only by the ADR plus a static-analysis rule.Vec of the wrong element type fails at consumption, not construction. Treat Vec as documentation plus runtime list enforcement, not as a sound type system.Ramp-up
One to two days for engineers already fluent in Collection or JavaScript array methods; the mental model transfers almost entirely. The real onboarding artifact is a short internal cheat-sheet mapping collect()->map(...) to the Vec equivalent, plus the explicit "when not to use this" list. Team unfamiliarity with functional chaining would push this to a week and, at 1 star and 0 dependents, is probably not worth the spend.
TPM verdict
Worth a bounded pilot, not a platform commitment. The opportunity signal (65) is offset by a low overall score (21.7) driven by adoption and maturity. Approve a time-boxed spike with a pre-agreed kill criterion; require an ADR before any second module adopts it; keep Collection as the default everywhere else.
How can I help you explore Laravel packages today?