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

Magic Query Laravel Package

mouf/magic-query

Magic Query lets PHP developers describe SQL queries in JSON instead of hand-written strings, then compiles them into parameterized SQL with joins, unions and filters handled automatically. This reduces injection risk and makes complex queries easier to build, reuse and maintain across projects.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. mouf/magic-query is a standalone SQL string compiler: you hand it a query template containing "magic" comments (conditional fragments, optional filters, array/IN expansion) plus a parameter bag, and it emits a concrete prepared statement with a matching, correctly ordered parameter set. Architecturally it replaces programmatic SQL construction (Laravel's query builder conditionals, when() chains, manual implode of placeholders) rather than integrating with Eloquent. That makes it a plausible fit for filter-heavy read paths — admin search screens, reporting endpoints, multi-select facets, optional sort/column lists — and a poor fit for CRUD persistence, relationships, or anything you want hydrated into models.

Integration feasibility. Composer-installable and framework-agnostic; usable in Laravel via a thin wrapper around a PDO/DBAL connection pulled from config/database.php. There is no service provider, facade, or Laravel-native ergonomics, so expect to write ~100 lines of glue. The main feasibility question is dependency overlap: it targets Doctrine DBAL, and Laravel's own connector layer is separate, so you are adding a second DB abstraction to the container. That is tolerable for a bounded module and undesirable if it leaks into shared infrastructure.

Technical risk. The dominant risk is the custom SQL parser sitting on the hot path. Hand-rolled SQL parsing has a long tail — CTEs, window functions, LATERAL/APPLY, vendor-specific LIMIT … OFFSET, quoted identifiers, nested subqueries, dollar-quoted strings, function calls with commas, and ordinary /* comments */ that may collide with the magic-comment syntax. Failures are runtime exceptions rather than compile-time errors, which means they surface in production on the query shapes your tests did not cover. Secondary risk is adoption signal: 20 stars and zero listed dependents means you are effectively the QA function for the parser; the June 2025 release is a positive maintenance signal but does not substitute for field-hardening. Upside risk is real: the approach removes a whole class of injection-prone string concatenation and makes dynamic SQL reviewable as data rather than code.

Key questions.

  • Which database engines are in the maintained test matrix, and is the parser dialect-neutral or MySQL-centric?
  • Is there a built-in parse cache, or is the SQL re-parsed on every execution?
  • How are empty arrays and single-element arrays handled in IN expansion — syntax error, NULL rewrite, or silent no-op?
  • Are parameter types inferred, or passed through to the driver as strings?
  • Is the parser an original implementation or a vendored fork, and what license obligations follow?
  • PHP and DBAL version constraints — do they resolve cleanly against the Laravel version in use?
  • Can arbitrary SQL fragments be injected as parameters, or are fragments restricted to code-supplied strings?
  • Test coverage and CI breadth; commit cadence over the last 24 months.

Integration Approach

Stack fit. Treat it as a query gateway, not a data layer. Introduce a single MagicQueryGateway (or per-module repository) that owns the connection handle, the query templates, and the parameter mapping; everything above it deals in DTOs and arrays, not raw SQL. Keep Eloquent for persistence and relationships, keep the query builder for simple static queries, and confine Magic Query to the conditional-heavy reads where it earns its complexity. This bounds the blast radius of a parser bug to a few endpoints and makes replacement a one-file change.

Migration path. Strangler pattern, not a rewrite. Candidate #1 is the endpoint with the ugliest existing conditional SQL — typically an admin list with 8–12 optional filters. Extract that query verbatim into a template, preserve the existing response shape, and ship behind the same route. For anything with meaningful traffic, shadow-run in staging: execute legacy and template versions against a snapshot dataset and diff result sets. Do not migrate queries that are already clean in the builder; the payoff is not there.

Compatibility. Pin the package version exactly and pin its DBAL constraint explicitly in composer.json so an unrelated composer update cannot shift the parser underneath you. Build a compatibility matrix across the engines you actually run (MySQL 8 / MariaDB / PostgreSQL / SQLite for tests) and a PHP-version check against your Laravel release. Confirm the license before distribution, especially if the parser is derived from another project.

Sequencing.

  1. Spike: five representative production queries (optional filters, IN lists, optional ordering, one subquery) run against a disposable branch. Timebox it; the spike is where you discover whether the parser survives your real SQL.
  2. Harness: golden-file tests asserting emitted SQL and bound-parameter order for each template, plus integration tests per engine.
  3. Wrapper + first module in production behind a config flag.
  4. Measure: parse overhead per request, p95 latency delta, error rate on the migrated endpoints.
  5. Decide the edge-case policy — accept, rewrite the query, or fork — before broader adoption.

Operational Impact

Maintenance. Small project, small maintainer pool; assume you own your usage. Pin versions, subscribe to release notifications, and read changelogs before upgrading — a parser change can alter emitted SQL without changing the API. If the package becomes load-bearing, budget for the possibility of a maintained fork; that is a real cost and should be priced into the adoption decision, not discovered later. The recent release cadence is the main reason this is viable at all.

Support. No commercial support. Internal ownership is mandatory: one named owner, a documented DSL cheat-sheet, and a lint or test that fails when a template uses unsupported constructs. On-call needs a runbook entry mapping parser exceptions to the offending template.

Scaling. Parsing is CPU work per execution; without an internal cache you are paying it on every call, which matters for high-QPS endpoints and is nearly free for admin traffic. Confirm whether a parse cache exists and, if not, wrap one keyed on template text plus the set of supplied parameter names (the shape of the query, not the values). Database-side scaling is unaffected, but large IN expansions inflate bound-parameter counts — watch placeholder limits and prepared-statement plan cache pollution when a filter accepts hundreds of IDs; chunk those explicitly. Empty-array handling is the sleeper scaling issue: it either errors under load or silently returns everything.

Failure modes.

  • Unsupported SQL construct → parse exception → 500 on a previously working endpoint. Highest likelihood, highest severity.
  • Empty or single-element IN list → malformed SQL or wrong cardinality.
  • Magic-comment syntax colliding with legitimate SQL comments or string literals containing /*.
  • Type coercion differences across drivers (string-bound integers, booleans on PostgreSQL).
  • Silent semantic change after a minor upgrade — emitted SQL differs, results differ, no error. Mitigations: golden-SQL tests in CI, per-engine integration tests, shadow-run diffing before cutover, canary rollout, and alerting on parser-exception rate distinct from generic 500s.

Ramp-up. A mid-level PHP developer can be productive in a day or two; the DSL is small. The real cost is reviewability — "clever" templating obscures intent from reviewers who have not internalized the syntax, so require the emitted SQL to be visible in tests and code review. Budget one sprint for spike + harness + first module for a team of two, and treat team unfamiliarity as the primary schedule risk rather than the library itself.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource