complex-heart/criteria
Bring the Criteria pattern to Laravel Eloquent with complex-heart/criteria. Encapsulate query constraints in reusable, composable classes so filtering stays clean, testable, and out of your models. Ideal for flexible repository queries and complex search logic.
Architecture fit. The package implements the Criteria pattern — encapsulating query intent as first-class objects that repositories translate into persistence-specific queries. This is a textbook DDD/hexagonal-architecture pattern and fits cleanly where the codebase already separates domain from infrastructure. It is a poorer fit for idiomatic Laravel, where Eloquent's ActiveRecord model, query scopes, and Builder chaining already provide a query-composition idiom. The honest framing is that this package is valuable only to teams that have deliberately adopted repository abstractions over Eloquent; for the median Laravel codebase it adds an indirection layer that competes with a framework-native solution the team already knows.
Integration feasibility. Technically low-friction: MIT-licensed, Composer-installable, and the Criteria pattern has a small surface area (criteria objects, an operator/comparison vocabulary, and a translator interface that the consuming repository implements). There is no runtime framework coupling implied by the description, so it should drop into a Laravel service provider as a plain library. The real cost is not installation but the adapter work: someone must write and own the criteria-to-Eloquent (or criteria-to-query-builder) translator, and that translator is where all the semantic risk lives.
Technical risk. The dominant risk is adoption and stewardship, not code quality. Five stars and zero dependents means effectively no external production validation, no community-reported edge cases, and no ecosystem of examples to learn from. "Complex Heart SDK" implies the package is a component of a larger, likely single-vendor suite; its roadmap and release cadence will follow that suite's priorities, not ours. The stated last release date (2026-08-11) is in the future relative to normal release metadata, which is either a data-pipeline artifact in the scoring source or a versioning anomaly — either way, treat the supplied metadata as unverified and confirm tags, changelog, and commit history directly before relying on it for a planning decision. Bus factor is plausibly one.
Key questions.
whereHas), or will we hit its ceiling in month two?Verdict. Evaluate, do not adopt by default. The pattern is sound and the integration cost is low, but a 5-star, zero-dependent dependency in a core data-access path requires either a credible maintenance commitment or an internal fork we are prepared to own.
Stack fit. Best fit: Laravel services that have already introduced a repository or port layer over persistence, particularly in a modular monolith or where multiple read models target the same domain. Poor fit: CRUD-heavy applications, teams standardized on Eloquent scopes, or codebases where the repository layer exists on paper but is bypassed in practice. Confirm fit by counting how many call sites would actually route through criteria versus continuing to use Model::query() — if the honest number is low, the abstraction is ceremony.
Migration path. Do not retrofit. Introduce criteria at the boundary of new bounded contexts or newly extracted modules, leaving existing Eloquent usage untouched. The migration shape is: define domain criteria objects alongside the domain entities; implement a translator behind an interface we own; make the repository the only component aware of both. Because the translator interface is ours, the package remains swappable — a thin internal implementation of the same pattern is a credible fallback if the dependency stalls.
Compatibility. Pin explicitly and test the matrix we actually run (PHP version, Laravel major). Because there are no dependents, we should assume untested combinations exist and treat the package's own CI as the only evidence — verify it rather than assume it. Check for conflicts with static analysis baselines (PHPStan/Psalm levels) and with any existing query-object or specification library already in the codebase; two overlapping query abstractions is worse than one imperfect one.
Sequencing.
Maintenance. Our maintenance burden is the translator and the criteria vocabulary mapping, not the library. Budget for the translator to be the highest-churn file in the data layer — every new query shape is a translator change. Because the upstream is small and single-vendor, plan for the possibility of owning the package outright; a private fork or a vendored copy with a documented patch queue is a reasonable steady state.
Support. Assume no vendor support and no community support. Internal expertise must be deliberate: name an owner for the data-access layer and require that person to review criteria additions. Documentation for the pattern is generic DDD literature, not package-specific, so onboarding material is ours to write.
Scaling. Architecturally the pattern scales fine — it is a thin abstraction over query construction and adds negligible runtime cost. The scaling risk is organizational: the translator becomes a shared bottleneck and a correctness chokepoint. As query volume grows, an under-designed translator produces silently incorrect SQL rather than loud failures, which is the worst failure mode for a data layer. Enforce translator test coverage with real database assertions, not mocks.
Failure modes.
Ramp-up. The Criteria pattern itself is learnable in a day by a mid-level engineer with DDD exposure, but the team must also internalize the translator's conventions and the discipline of not escaping the repository. Expect roughly one sprint of productivity dip for engineers new to the pattern, concentrated in code review rather than writing. Mitigate with two or three exemplar criteria-plus-translator pairs committed as reference implementations, and a review checklist that specifically asks whether a new criteria object is reused or a one-off.
Bottom line. The package is a small, correctly scoped implementation of a valuable pattern, undermined as a dependency by near-zero adoption and single-vendor stewardship. Recommend a short verification spike followed by a proof of concept; the likely best outcome is adopting the pattern with an internally owned translator, treating the package as reference implementation rather than load-bearing dependency.
How can I help you explore Laravel packages today?