aminsamadzadeh/simorgh
Simorgh is a Laravel package that provides a flexible, developer-friendly toolkit for building PHP applications. It offers reusable components and simple configuration to reduce boilerplate, streamline common backend tasks, and help teams ship maintainable Laravel projects faster.
Architecture fit
aminsamadzadeh/simorgh targets a narrow, well-understood seam in a Laravel application: translating HTTP request parameters into Eloquent query constraints. It sits between the controller/FormRequest layer and the Eloquent builder, which is the same position occupied by spatie/laravel-query-builder and hand-rolled filter traits. That is a legitimate architectural slot for read-heavy JSON APIs (list/index endpoints with filtering, sorting, pagination, and relation inclusion), and it composes cleanly with API Resources, FormRequests, and policies.
The fit is good in principle but shallow in practice. The package appears to solve one concern with a small public surface (likely a trait, scope, or facade), meaning adoption cost is low and blast radius is contained to whichever controllers opt in. It is not a framework-level dependency and does not force a data-access rewrite.
Integration feasibility
Composer-installable, Laravel package discovery, no infrastructure requirements, no external services, no schema changes. Integration effort is measured in hours for a spike and days for a hardened rollout. The realistic friction is not installation — it is the Laravel/PHP version constraints frozen at a November 2020 release, which likely caps support at Laravel 6–8 and PHP 7.x. On a modern Laravel 10/11 codebase, this is a fork-and-patch exercise, not a composer require.
Technical risk This is where the package fails as a low-risk adoption:
GET directly. Whether this package whitelists anything is unknown and must be verified in source, not docs.include combinations are a cheap denial-of-service vector: unindexed LIKE scans, deep relation eager-loads producing cartesian blowups, and arbitrarily large page sizes.Key questions
composer.json constraints permit, and does the test suite pass against our target version?whereRaw, or bound parameters through the builder?with), and does it guard against N+1 and recursive nesting?spatie/laravel-query-builder — is there any capability this package offers that a maintained alternative does not?Stack fit Fits a conventional Laravel API stack (Laravel + Eloquent + API Resources + FormRequests). It is a read-path convenience, not a persistence or domain-layer component, so it does not constrain domain modeling. It fits poorly in codebases that already standardize on a vetted query-builder package, since running two filter grammars in one API creates inconsistent client contracts.
Migration path Do not adopt directly into production controllers. The correct path is a bounded spike:
QueryFilterApplicator) so controllers depend on our abstraction, not the vendor API. This is the single highest-value decision here: it converts a stale third-party dependency into a swappable implementation detail and makes the eventual replacement with spatie/laravel-query-builder or an in-house trait a one-file change.For most teams the honest recommendation is that the spike exists to evaluate, and the likely outcome is building or adopting in-house — the package is small enough that its value is mostly as a reference implementation of the pattern.
Compatibility Expect to own compatibility. Pin exact versions, add the fork to CI with a Laravel version matrix, and treat every framework upgrade as requiring a review of this package. If the fork cannot be made to pass on our target framework within the timebox, that is a hard stop, not a workaround.
Sequencing Security review of the query construction path before any endpoint exposure; adapter layer before the first production controller; observability (query logging, slow-query alerts) before scaling beyond the pilot; documented allowlists per endpoint before opening to external clients. Do not sequence security review after the pilot — the pilot is exactly where unwhitelisted field access would surface as a real exposure.
Maintenance Effectively a fork-and-own dependency. Budget ongoing effort for framework-upgrade patches, security review of the query path, and dependency updates. This is low absolute hours but non-zero and perpetual, and it must be assigned to a named owner — an unowned fork is worse than no package.
Support No vendor, no SLA, no security contact. Support is GitHub issues with a single maintainer and an 11-star project; assume no response. Internal documentation of the filter grammar and allowlist conventions is mandatory, because it will not come from upstream.
Scaling
The generator itself is cheap; the queries it produces are the scaling risk. Under load, expect unindexed filter columns to degrade first, followed by eager-load amplification from relation includes and oversized page requests. Mitigations: per-endpoint allowlists, enforced max page size, include depth limits, statement timeouts at the database/proxy layer, rate limiting on list endpoints, and slow-query alerting tied to endpoint. Without these, the package converts client creativity directly into database load.
Failure modes
Ramp-up The API surface is small, so engineer ramp-up is measured in hours — but the grammar is likely undocumented, meaning engineers read the source rather than docs. That concentrates knowledge in whoever did the spike, which is a real continuity risk for a component that touches every list endpoint. Mitigate with an internal README covering the grammar, the allowlist pattern, and the adapter interface, plus at least two engineers through the pilot.
Bottom line for a TPM: low integration cost, low architectural risk, high ownership risk. This package is only defensible behind an internal abstraction and an explicit allowlist layer, with a named owner and a documented exit path. Absent those three, the expected cost of ownership exceeds the cost of building the equivalent in-house.
How can I help you explore Laravel packages today?