awes-io/repository
A Laravel repository pattern package that streamlines data access with reusable repositories, query filtering, sorting, pagination, eager loading, and CRUD helpers. It keeps controllers lean and models clean while making complex Eloquent queries easier to organize.
Architecture fit. awes-io/repository implements the classic Repository pattern on top of Eloquent, adding two opinionated layers: query criteria (composable, reusable query fragments) and request-driven filters (query-string → query constraints out of the box). This is a strong fit for Laravel applications that expose filterable list endpoints — admin panels, back-office CRUD, search/listing APIs — and for teams that want a DDD-ish separation between HTTP, application service, and persistence layers. It is a weaker fit for teams that have already standardized on query objects, Spatie Query Builder, or Laravel Scout, and for teams that accept Eloquent models as the domain layer (the package adds indirection without removing Eloquent). Note the architectural tension: request-driven filtering couples the HTTP contract to persistence concerns, which is convenient but requires strict allowlisting to avoid exposing unintended columns or expensive query paths.
Integration feasibility. Integration surface is small and conventional: Composer install, auto-discovered service provider, an abstract base repository to extend, criteria classes, and filter classes. Greenfield adoption is a low-effort, single-sprint activity for one bounded module. Brownfield adoption is materially harder — existing bespoke repositories, custom query builders, and hand-rolled filter logic create duplicate abstractions and ambiguous ownership of query construction. The real feasibility question is version support: last release is June 2021 (Laravel 8 era), so modern Laravel 10/11/12 and PHP 8.2/8.3 compatibility must be verified empirically, not assumed.
Technical risk. Principal risks, in order: (1) Maintenance staleness — no release in ~4 years implies the package may not resolve against current laravel/framework constraints without a fork or composer.json patch; (2) Bus factor / ecosystem depth — 170 stars and a single-maintainer profile means no vendor SLA, thin issue triage, and limited community answers; (3) Security posture of request-driven filtering — if filterable fields are not explicitly allowlisted, the pattern invites over-posting-style data exposure and unbounded query construction; (4) Query performance opacity — chained criteria and filters can produce N+1s or unindexed scans that are invisible at the call site; (5) Lock-in via inheritance — extending the package base class directly spreads its API across the codebase and raises exit cost. MIT licensing is clean and carries no commercial risk.
Key questions. Which Laravel and PHP versions does the current composer.json permit, and does it actually pass tests on our target matrix? Who maintains it upstream, and is there a maintained fork? How are filterable fields allowlisted and validated, and is there a safe default-deny mode? Does it compose with pagination, eager loading, caching, and read/write connection splitting? What is the query-count and latency profile for a 5-filter, 3-criteria listing against a representative table? What is our exit plan if the package is abandoned — can we replace it without touching domain code? Is there meaningful test coverage we can rely on as a regression baseline?
Stack fit. Best fit: Laravel monolith or modular monolith, Eloquent-backed relational data, JSON APIs and admin UIs where listing endpoints dominate the surface area, and teams already comfortable with repository/criteria conventions. Poor fit: event-sourced or CQRS-heavy architectures, Elasticsearch/Scout-primary search, projects on the newest Laravel major with a hard requirement for first-party dependency currency, and teams with fewer than ~3 backend engineers (the abstraction cost is not amortized).
Migration path. Do not retrofit existing repositories. Instead: (1) wrap the package behind an internal BaseRepository that we own and that extends the package class — domain code depends on our class, never the vendor class; (2) pilot on one bounded read-heavy module (an admin listing page is ideal); (3) express domain query intent as criteria so business rules do not live in controllers; (4) require explicit filter allowlists declared per repository, with a code-review gate; (5) only then expand module by module, retiring hand-rolled filter code as each module migrates. Keep the vendor dependency pinned and isolated to a single Composer requirement so removal is a one-file change plus class swaps.
Compatibility. Treat version support as a gating experiment, not an assumption. Run composer why-not awes-io/repository against our target Laravel/PHP, execute the package's test suite on our PHP version, and run static analysis (PHPStan/Larastan) over the integration. If the constraint tree fails on our framework version, decide explicitly between a pinned older Laravel, a maintained fork, or rejection — do not silently patch composer.json in production without an owner.
Sequencing.
BaseRepository, one module migrated, integration tests, query logging enabled.Maintenance. Assume we own the dependency. Budget a recurring line item for dependency review each Laravel major release, and designate a named maintainer. Because upstream has been quiet since 2021, plan for one of three states: upstream resumes, we consume a community fork, or we vendor/fork the package internally. Prefer the fork over ad-hoc composer.json patches so upgrades are reproducible. Keep the package confined to the adapter layer so that a fork swap is a single-PR change.
Support. Community-only support via GitHub issues; with ~170 stars, expect slow or no responses and few Stack Overflow answers. Mitigation is internal: a short runbook covering how criteria and filters compose, the allowlist convention, how to debug a generated query, and where the base class lives. Do not let the package become "the thing only one engineer understands."
Scaling. The dominant scaling risk is unbounded, user-driven query construction. Enforce a maximum number of active filters, a required pagination cap, per-request query timeouts at the database or middleware layer, and mandatory index review for any newly filterable column. Watch for lazy-loaded relations inside criteria producing N+1s; mandate explicit eager loading in repository methods. Repository indirection itself scales fine horizontally — the risk is query shape, not the pattern.
Failure modes. (1) A Laravel upgrade blocked by a stale constraint, freezing the whole application on an old framework — the highest-probability, highest-cost failure. (2) Data exposure via a filterable field that was not allowlisted. (3) Latency incidents from a combinatorial filter set hitting unindexed columns. (4) Silent behavior drift when a fork diverges from upstream semantics. (5) Abstraction sprawl — competing repository conventions appearing in different modules, eroding the benefit. Each has a cheap mitigation: pinned versions, allowlists, query budgets, a fork changelog, and one written convention.
Ramp-up. For a Laravel-fluent engineer, the repository pattern and the package's API are learnable in roughly one to three days; criteria composition and the filter allowlist convention add another day. Engineers without repository-pattern background will take longer and may initially fight the abstraction — pair them on the first module. Invest in two or three worked examples in the repo (one simple CRUD listing, one multi-criteria filtered endpoint, one custom filter) rather than relying on upstream docs, which are likely thin and version-stale.
How can I help you explore Laravel packages today?