Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

L5 Repository Laravel Package

plum/l5-repository

Laravel package that adds repositories, criteria, presenters, and transformers to your applications for cleaner, testable data access. Supports caching, request criteria, and easy model swapping—a practical way to organize query logic and keep controllers and models lean.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

plum/l5-repository (namespace Prettus\Repository) implements the classic repository pattern on top of Eloquent: BaseRepository / RepositoryEloquent provide a CRUD contract (all, find, create, update, delete, paginate), and a Criteria pipeline lets you push composable query modifiers (pushCriteria, skipCriteria, scopeQuery) ahead of execution. Optional traits add presenters (Fractal transformers) and repository-level caching. Artisan generators (make:repository, make:criteria, make:presenter, make:entity, make:bindings) scaffold the wiring.

The architectural question a TPM should force early: Eloquent already is a data-access abstraction. Adopting this package buys you (a) a swappable, mockable interface per aggregate, (b) a reusable cross-cutting filter mechanism (RequestCriteria turns ?search=, ?filter=, ?order= into a query without hand-written controller code), and (c) a place to hang caching. It costs you one class per aggregate, an interface + binding per aggregate, and a layer that leaks whenever a caller needs Eloquent-specific power (chunking, cursors, complex joins, upsert, relationship aggregates). Fit is strongest for CRUD-heavy internal APIs, admin panels, and multi-tenant apps where a single criteria (tenant scoping, soft-delete policy, authorization filter) must apply uniformly. Fit is weak for reporting, event-sourced, or read-model-heavy services.

Integration feasibility

Low friction mechanically: composer require plum/l5-repository, publish config/repository.php, register RepositoryServiceProvider (or a project-owned provider binding Interface::class => ConcreteRepository::class). A single aggregate can be migrated in an afternoon; the generators make the 20th repository as cheap as the first. No database changes, no schema opinions, no runtime service dependency. Reversible — delete the provider bindings and the layer is gone.

Technical risk

  • Version drift is the primary risk. Illuminate/PHP constraint compatibility across Laravel 9–12 is the gating item. The metadata's "last release 2026-05-27" cannot be reconciled with a package of this vintage and should be treated as unverified; the real check is a composer why-not against the target Laravel and PHP versions before any design work. Historical maintenance has been single-maintainer and intermittent.
  • Dependents: 0 is almost certainly an undercount or missing data (4,195 stars is inconsistent with zero downstream consumers). Do not read it as abandonment evidence either way — verify against Packagist's actual dependent count and GitHub issue/PR latency.
  • Criteria is a hidden control-flow channel. Globally pushed criteria (typically in boot()) apply to every query on that repository. Silent filters — an unexpected tenant scope, an eager-load, an orderBy — are the most common production surprise and are painful to trace because the SQL is assembled in a class the debugging developer never opened.
  • RequestCriteria with $fieldSearchable misconfigured exposes column-level filtering/searching to arbitrary client input. Treat fieldSearchable as a security-reviewed allowlist, not boilerplate.
  • Cache invalidation is the sharpest edge. CacheableRepository requires a taggable cache store (Redis/Memcached/array) — file and database stores silently fail or throw. Critically, invalidation is driven by the repository's own write methods, so writes that bypass the repository (queue jobs, console commands, raw DB:: queries, other services, sibling repositories on the same table) leave stale cache with no signal.
  • Presenter/Fractal overlap with native Eloquent API Resources is redundant if the app already standardizes on Resources; mixing both produces two serialization conventions.

Key questions

  1. Which Laravel and PHP versions must we support, and does the package's constraint set actually satisfy them today?
  2. Do we have a concrete aggregate where interface swapping or criteria reuse pays for the indirection, or is this pattern-driven?
  3. Who owns the fork if upstream stalls — is patching a vendored dependency acceptable to the team?
  4. Is the cache store taggable in every environment, and can we guarantee all writes to cached tables route through the repository?
  5. Does RequestCriteria shipping enabled-by-default match our threat model for public endpoints?

Integration Approach

Stack fit

Natural fit for a conventional Laravel monolith or modular monolith using service classes over Eloquent, especially where controllers are thin and the team has already accepted some form of layered architecture. Poor fit where the codebase leans on Eloquent expressiveness (query scopes, relationships as first-class), or where livewire/Inertia-style direct model usage is the norm — the repository layer becomes a competing convention.

Migration path

Strangler, not rewrite. Introduce the package in one bounded context, behind the existing service layer, so callers are unchanged and the repository is an implementation detail of the service. Do not let controllers depend on RepositoryInterface directly in the first wave; that couples the whole app to a third-party contract before you have evidence the layer earns its keep. Convert the second aggregate only after the first has shipped and been debugged.

Compatibility

Pin exact versions. Verify the illuminate/support constraint, PHP constraint, and the Fractal version pulled transitively. Run the generators against the target Laravel version in a scratch branch — generator command signatures are a common breakage point across Laravel majors. If the app uses Laravel's native API Resources, disable presenters outright rather than running both.

Sequencing

  1. Spike (1–2 days): install in a branch, generate one repository + criteria, confirm PHP/Laravel constraint resolution, confirm cache driver taggability in all environments.
  2. Pilot aggregate: a read-heavy, low-blast-radius module. Bind the interface, move one or two call sites, measure nothing but correctness.
  3. Cross-cutting criteria: codify tenant scoping and authorization as named criteria with unit tests asserting the generated SQL/query. Decide explicitly whether RequestCriteria is opt-in per repository (recommended) or global.
  4. Caching: only after writes are provably repository-contained. Start with a short TTL as a safety net behind correct invalidation, not as the invalidation strategy.
  5. Standardize or stop: publish a one-page convention doc (naming, when not to use a repository, fieldSearchable rules) and then require it in review. Expansion beyond the pilot without that doc is how these layers sprawl.

Operational Impact

Maintenance

Ongoing cost is class-count, not dependency risk: every aggregate carries an interface, a repository, a binding, and often a presenter — roughly 3–4 files of boilerplate where Eloquent needed zero. That is manageable when the generators are used and review enforces convention, and corrosive when half the team writes repositories and half queries models directly. Upstream maintenance is the second-order cost; budget for the possibility that a Laravel major requires a community fork or a local patch, and keep the package's blast radius narrow enough that forking is survivable.

Support

Internal: a mid-level Laravel developer is productive in 2–3 days; the failure modes (criteria ordering, silent global criteria) take a senior reviewer to catch, so pair the adoption with code-review guidance rather than training alone. External: community support is GitHub-issues-grade with no SLA and an intermittent maintainer. Treat it as "supported by the team" from day one; there is no vendor to escalate to.

Scaling

Application-level scaling is fine — the layer adds one method call per query. Two things scale badly. First, criteria accumulation: global criteria lists grow append-only and each adds a query mutation whose interactions are untested combinatorially; audit that list quarterly. Second, cache key and tag growth in Redis as cached repositories multiply — taggable invalidation is cheap per key but tag sets can grow large on high-cardinality caches, so define a key-prefix convention and watch tag memory.

Failure modes

  • Stale reads from out-of-band writes — the highest-severity failure. Mitigate with short TTLs, an explicit "all writes go through the repository" rule, and cache-bypass flags for critical paths.
  • Silently over-filtered results from a globally pushed criteria — manifests as missing rows, not errors. Mitigate with criteria unit tests and a debug path (skipCriteria in tests, query-log assertions).
  • Untraceable SQL during incident response — repository + criteria + presenter means the query is assembled three layers from the controller. Mitigate with query logging in non-prod and a documented "where the SQL comes from" runbook note.
  • Cache store misconfiguration — taggable operations against a non-taggable driver fail at runtime, often only on the first cached read in an environment.
  • Generator drift after a Laravel/PHP upgrade — scaffolded code that no longer matches framework conventions; caught only by actually running the generators post-upgrade.

Ramp-up

Two to three days to first productive commit for a Laravel-fluent developer; two to three weeks before they can reliably diagnose criteria and caching behavior in production. The senior-review requirement never goes away entirely, which is the honest operational price of the abstraction — if the team cannot sustain that review capacity, the correct decision is to skip this package and lean on Eloquent scopes plus a thin service layer for the same cross-cutting concerns.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib