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

Sqlquery Laravel Package

aura/sqlquery

Independent query builders for MySQL, Postgres, SQLite, and SQL Server that work without any database connection library. Build SQL strings cleanly, with PDO recommended for execution.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Release Delta — 7.0.0-beta2

The second beta of the 7.x line. It does not add features so much as rework the ? placeholder machinery introduced in beta1 and reverse two of its behaviours. That rework is the most consequential change to the prior assessment:

Change Impact on assessment
A ? given a value is now bound under a generated name (__1__, __2__); getBindValues() returns ['__1__' => 5] instead of [0 => 5] Statements can no longer mix ? with named placeholders — which plain PDO rejects on MySQL/PostgreSQL and which pdo_sqlite silently ran with the ? unbound. A real correctness fix. But any code reaching binds by numeric index (getBindValues()[0], bindValue(0, ...)) breaks
? placeholders in separate where() calls no longer throw (reverses a beta1 behaviour) Retires what the prior assessment called the single largest upgrade risk — the multi-? case — for positional bindings. The named-placeholder reuse rule is unchanged
Value/? count mismatch now throws InvalidArgumentException for any count, not just lists/sub-selects Placeholder typos and edit-time drift fail at build instead of at execute or silently
Values passed with a closure condition now fill the ? its conditions leave unfilled, in reading order, under names allocated before the closure runs New, genuinely useful ergonomics for grouped conditions; the ordering rule is subtle and needs a test, not a reading
?? (PDO's literal-? escape) not treated as a placeholder; ? inside comments and string literals ignored, dialect-aware (MySQL # comments, -- only before whitespace, PostgreSQL E'...' and $$...$$) Correctness for raw SQL, and a reminder that this scanning is heuristic and dialect-coupled
resetWhere()/resetHaving()/resetTables()/resetUnions()/resetWith() drop generated values their clause bound, unless a rendered UNION branch still spells them Prevents orphan parameters that PDO rejects at execute. The union carve-out is the exception to understand
Select::$text_pattern removed; subclasses must override getTextPattern() instead (reading moved to AbstractQuery) A subclass written against beta1 that overrode the property is silently ignored — no fatal, no deprecation. Worst failure shape in the release
New Pgsql\Quoter leaves dollar-quoted strings ($$...$$, $tag$...$tag$) as written; previously where('a = $$t.c$$') compared against "t"."c" (#274) Correctness win, PostgreSQL only; other dialects unchanged

Release Delta — 7.0.0-beta1 (status after beta2)

Still in force unless marked:

Change Status
PHP 8.4 minimum (CI on 8.4/8.5) Unchanged — still the gating prerequisite
Native param/return/property types everywhere; 166 static-returning methods Unchanged — still a load-time fatal for mismatched overrides
WithInterface (with(), withRecursive(), resetWith(), hasWith()) on all four query types Unchanged — still the flagship justification
Aura\SqlQuery\Exception deprecated in favour of ExceptionInterface; removal in 8.x Unchanged — still scheduled debt if written against
Duplicate named placeholders across clauses throw Unchanged for names; the positional ? half is superseded by beta2's generated-name binding
reset() returns static; union()/unionAll() take optional ?SelectInterface; join()/joinSubSelect() take array $bind; subSelect() moved to AbstractQuery with $source; rebuildCondAndBindValues() takes $clause; getStatement() abstract; getLastInsertIdName() narrowed Unchanged

The pattern to note: beta2 reversed two behaviours beta1 introduced, one release apart. That is normal for a first-of-line beta, and it is also the clearest evidence available that the placeholder contract is not yet settled.

Architecture Fit

  • Strengths (retained):

    • Database-agnostic design — MySQL, PostgreSQL, SQLite, SQL Server via QueryFactory and per-dialect quoters.
    • Fluent interface with the 7.x typing making the $this contract enforceable rather than docblock-only.
    • Subquery support — fromSubSelect()/joinSubSelect() accept any SelectInterface, so adapter-supplied builders nest without unwrapping.
    • Extensibility through QueryInterface and traits (WhereTrait, WithTrait).
  • Strengths (new or strengthened in beta2):

    • One parameter style, always. Because every ? with a value becomes a name, the generated statement is uniformly name-bound. This is a better contract for an adapter, for logging, and for PDO — it structurally eliminates the mixed-style statement that MySQL/PostgreSQL drivers reject and that SQLite ran with a hole in it.
    • Closure-condition binding. Passing values through a closure (where(fn ($q) => $q->where('a = ?')->where('b = ?', [6]), [5])) now distributes them into the unfilled placeholders in reading order. This makes nested/grouped predicates composable in a way they were not in 3.x and were not in beta1.
    • reset*() hygiene. Dropping generated values when their clause is cleared is what makes the generated-name scheme survivable in long-lived builders — without it, every resetWhere() would leave a binding PDO rejects.
    • Dialect-aware literal scanning. Ignoring ? inside comments, string literals, E'...' and dollar-quoted blocks — and the PostgreSQL quoter no longer mangling $$...$$ — removes a class of wrong-SQL bugs that previously only showed up in production data.
  • Gaps vs. Laravel:

    • No Eloquent integration — relationships, model events, serialization need a wrapper.
    • No query caching; SQL is generated per call.
    • Limited raw expression support relative to DB::raw().
    • Rigid type surface — matching native types and 166 static returns makes "thin wrapper" considerably less thin; composition should be the default.
    • Strict/coercive boundary split — the package declares no strict_types, so behaviour depends on the calling file; cast at the edge.
    • New: generated names are internal and not a public contract. getBindValues() keys look like a stable API (__1__) but are allocated per render and released on reset. Treat them as opaque — the moment an adapter or a test asserts on __1__, it has coupled to an implementation detail.

Integration Feasibility

  • Laravel stack compatibility:

    • PHP ≥ 8.4 remains the gating constraint — verify the runtime matrix first, before merit is discussed.
    • PDO integration unchanged; in fact improved, since statements are now uniformly named.
    • Handing binds to Laravel: because getBindValues() is string-keyed, it can be passed to DB::select($sql, $bindings) — Laravel's bind path preserves array keys and PDO accepts named parameters. Verify against your Laravel version rather than assuming; the previous numeric-key convention masked this question entirely.
    • Service provider / facade / macro: unchanged; QueryFactory as a singleton remains correct.
  • Key integration points (updated):

    Laravel Component Aura.SqlQuery 7.x Equivalent Integration Approach
    DB::select() Select Wrap; forward name-keyed binds.
    DB::table()->where() Select::from()->where() Compose, don't extend — extension inherits the 166-static conformance tax.
    DB::raw() Manual strings fromRaw()/whereRaw(); now safer on PostgreSQL thanks to #274.
    (no equivalent) with(), withRecursive() Primary use case — CTEs Laravel cannot express.
    Upserts OnConflictUpdateInterface (Pgsql/SQLite) Dialect-correct ON CONFLICT.
    Eloquent relationships CTEs / subqueries Custom accessors; no relationship layer.
    Query scopes Fluent methods Rewrite; not reusable as-is.
    DB::transaction() None Keep in Laravel; compose at the call site.
  • Adapter-layer feasibility (improved but still bounded): the beta1 concern about positional binds across separate where() calls is gone — those now work. The remaining tax is name-keyed: an adapter must never index binds numerically, never assume name stability, and must surface a stable toSql()/getBindings() pair to consumers. getTextPattern() replaces the removed $text_pattern property for any dialect-specific text handling.

Technical Risk

  • High:

    • PHP 8.4 runtime floor — coordinated infrastructure change across base images, CI, local dev and production fleets before anything ships. Unchanged.
    • Fatal-on-load signature mismatches — overriding any of the 166 static methods or redeclaring a typed property fatals at autoload. Loud, but total for the affected path.
    • Silent override loss on $text_pattern — a beta1-era subclass that overrode the property now has no effect and no warning. Text-pattern behaviour silently falls back to the parent. This is the one failure in the release that neither static analysis nor a load-time fatal will catch.
    • Numeric bind access breaks — getBindValues()[0], bindValue(0, ...), array_values()-then-reindex assumptions, and any test asserting on binding shape. Not findable by type checking alone; getBindValues() return type is array either way.
    • Beta maturity, now with observed churn — two behaviours introduced in beta1 were reversed in beta2, and a protected property was removed without a deprecation cycle. Budget for at least one more such round.
    • Named placeholder reuse still throws — the beta1 rule for names across cols()/where()/having() is unchanged.
    • Deprecation debt — Aura\SqlQuery\Exception is deprecated and slated for removal in 8.x; write against ExceptionInterface now.
    • Orphan-parameter edge cases — reset*() drops generated values unless a rendered UNION branch still spells them. Builders reused across union construction and reset are the place to look for "parameter count does not match" errors at execute.
  • Reduced or closed risk (new in beta2):

    • Mixed ?/named statements — structurally impossible now; previously a hard PDO failure on MySQL/PostgreSQL and a silent unbound placeholders on SQLite.
    • Positional ? collision across separate where() calls — closed (throws in beta1 → works in beta2).
    • ? count mismatch — now always throws, at build time.
    • Dollar-quoted PostgreSQL strings corrupted into "t"."c" — fixed (#274).
    • Previously closed in beta1 and still closed: named-placeholder silent clobbering, silent LIMIT drop, docblock/implementation drift.
  • Mitigation strategies:

    • Bind-key audit (replaces beta1's rename-collision exercise for positionals): grep for getBindValues()[, bindValue(0, bindValue($i, array_values(...getBindValues()), and any test fixture asserting a bind-array shape. Named-placeholder reuse across clauses still needs the code-review sweep.
    • Treat generated names as opaque — no assertions, no logging contracts, no persistence of __N__ keys.
    • Override getTextPattern(), not the removed property; grep for text_pattern across the codebase and in any vendored fork.
    • Pin the beta exactly; do not float to ^7.0.
    • Prefer composition to sidestep the signature-matching surface entirely.
    • Catch ExceptionInterface, not the deprecated interface.
    • Cast limit/offset to int at the edge so strict and non-strict callers behave identically.
    • Test closure-condition binding explicitly — reading order and pre-allocation of names are easy to get wrong and easy to regress.
    • Benchmark CTE and union paths, including the per-query placeholder scan, before general rollout.

Key Questions

  1. Use case justification — unchanged in substance: the case now rests on CTEs and dialect-correct upserts, not subqueries. Is that scope enough to justify a beta dependency?
  2. PHP 8.4 readiness — which apps, CI pipelines and images remain on 8.2/8.3, and what is the timeline? Nothing else can start until this closes.
  3. Bind-value consumers — who reads getBindValues() by index, replaces a bind by position, or asserts on binding shape in tests? Was the beta1 remediation plan built around renaming ? placeholders, and does it now need to be rewritten around key access instead?
  4. text_pattern overrides — does any subclass, fork or vendored copy override it? If so, who converts it to getTextPattern() and how is the silent-failure case detected in review?
  5. Adapter design — composition or inheritance? If inheritance, who owns conformance across 166 static methods and typed properties, and is PHPStan/Rector at max level gating merges?
  6. Beta exit criteria — what must be true before production use? Given beta2 reversed two beta1 behaviours and removed a protected property without notice, what is the acceptable change budget between now and GA, and is the team funded to absorb another round?
  7. Exception migration — is the codebase ready to catch ExceptionInterface so the 8.x removal is a non-event?
  8. Adoption scope and performance — reporting/CTE paths only, or general query building? Have CTE and union paths been benchmarked, including the placeholder-scan cost in hot loops?
  9. Union + reset interaction — does any builder get built, unioned and partially reset in the same instance? That is the carve-out where generated values can survive their clause and produce execute-time parameter-count errors.

Integration Approach

Stack Fit

  • Runtime prerequisite: PHP ≥ 8.4 across dev, CI and production, with a Laravel version whose supported range includes it. Separate, earlier track with its own owner.
  • Database layer: unchanged — PDO for MySQL, PostgreSQL, SQLite, SQL Server.
  • Service container: QueryFactory as singleton or contextual binding; no change required by beta2.
  • Flagship capability: CTEs (with(), withRecursive()), exposed through a dedicated reporting repository rather than bolted onto general Eloquent usage.
  • Parameter contract (new emphasis): the adapter always emits named parameters. Surface that as toSql(): string + getBindings(): array where bindings are string-keyed and names are opaque. This is a cleaner contract than 3.x or beta1 offered, and it is the piece consumers must not over-fit to.
  • Error handling: catch Aura\SqlQuery\ExceptionInterface. Every concrete exception derives from \LogicException, so broad catch (\LogicException) blocks silently absorb package errors — audit existing handlers.
  • Tooling synergy: Laravel Scout/Nova/Echo scenarios unchanged; CTE support strengthens the analytics and Nova-tooling case.

Migration Path

Phase Actionable Steps Tools/Dependencies
0. Runtime PHP 8.4+ everywhere; CI matrix and base images. Docker, GitHub Actions, platform runtime config.
1. Static audit Find subclasses, adapters, property redeclarations; find text_pattern overrides; find numeric bind access; find named-placeholder reuse across clauses. PHPStan (max), Rector, ripgrep.
2. Sandbox Pin 7.0.0-beta2 explicitly alongside existing 3.x usage in a branch. Composer with an exact pre-release constraint.
3. Signature remediation Match native types and static returns; redeclare properties with identical types; implement getStatement() on custom query types; add $source/$clause to overridden subSelect()/rebuildCondAndBindValues(); replace $text_pattern overrides with getTextPattern(). PHPUnit/Pest, static analysis in CI.
4. Bind remediation Replace numeric-index bind reads and positional replacements with name-based access where names are the caller's own; where the name is generated, restructure to use bindValues() or a named placeholder instead. Rename colliding named placeholders across cols()/where()/having(). Drop beta1 plans that renamed ? placeholders in separate where() calls — those now work. Code review; per-query integration tests.
5. Exception migration Replace catch (Aura\SqlQuery\Exception) with ExceptionInterface; remove direct instantiation/subclassing of the old interface. Rector rule, static analysis.
6. Adapter Build the facade/macro using composition; expose opaque name-keyed bindings; cast limit/offset at the edge. Laravel facades, macros, strict_types=1.
7. CTE adoption Move one reporting query to with()/withRecursive() behind a flag; compare rows and latency against the DB::raw() version. Debugbar, Blackfire/Tideways.
8. Rollout Expand to the audited set; hold general query building on Laravel's native builder. Env feature toggles, Horizon for queue-side visibility.
9. GA gate Re-evaluate at 7.0.0 stable; re-run phases 3–5 against GA deltas. Release notes, docs/upgrading.md.

There is no incremental path from 3.x — four majors are skipped. docs/upgrading.md is the only supported guide, and after beta2 it should be assumed incomplete with respect to the betas themselves; the beta release notes are the authority for beta1→beta2 deltas.

Compatibility

  • Laravel Query Builder:
    • Supported: select(), from(), where(), join(), groupBy(), orderBy(), limit(), offset(), union()/unionAll(), with()/withRecursive().
    • Unsupported: pluck(), chunk(), cursor(), Eloquent methods (note the with() naming collision between CTEs and eager loading), relationship methods.
    • Changed semantics: reset() returns static; limit()/offset() no longer coerce non-numeric strings; getBindValues() keys are names, not integers; ?/named mixing is impossible; reset*() may drop bindings you did not add by name.
  • Eloquent: keep it for CRUD and relationships; use Aura for CTE reporting and dialect-specific upserts, exposed through repositories. newQuery() overrides returning a composed builder remain the recommended seam.
  • Database drivers: MySQL, PostgreSQL, SQLite, SQL Server via PDO; Pgsql and SQLite exposes OnConflictUpdateInterface. PostgreSQL gains correct dollar-quoted literal handling. SQL Server vendor clauses (OUTPUT) still require extending SqlServerQuoter.
  • Laravel bind forwarding: name-keyed arrays should pass through DB::select() intact — verify on your version; this is newly relevant because bind arrays changed shape.
  • Strict types: behaviour depends on the calling file. Declare strict_types=1 in adapter code and cast at boundaries.

Operational Impact

Maintenance

  • Net shift: typed methods and properties remove upstream docblock drift, but the adapter becomes signature-sensitive — upstream changes are load-time fatals rather than silent mismatches. Loud and unavoidable is the better trade.
  • New: generated-name coupling risk. Bind keys are allocated per render and released on reset. Any log parser, test assertion, or observability hook that pattern-matches __1__ is a latent break. Publish an internal rule: bind keys are opaque.
  • Beta churn is now measured, not hypothetical. One beta reversed two prior behaviours and removed a protected property without deprecation. Budget a re-run of migration phases 3–5 at beta3 (if any) and again at GA.
  • Deprecation runway: Aura\SqlQuery\Exception → ExceptionInterface before 8.x, or pay a second breaking change shortly after this one.
  • Ownership: a named owner for the adapter layer and one for the bind/placeholder inventory. Both degrade silently otherwise. Track Aura and Laravel release notes together — the PHP floor couples the two cadences.

Support

  • Diagnostics improved again. InvalidArgumentException on a ?/value count mismatch, and a named-placeholder collision message, are far easier to triage than a wrong row count or a dropped LIMIT. Support cost per incident should fall even as incident count briefly rises.
  • New runbook entries:
    • "Parameter count does not match" at execute → check for a builder that was unioned then partially reset; generated values may survive if a rendered union branch still spells them.
    • "I used to get my value at index 0" → binds are name-keyed now; use your own names, or bindValues() for intentional overwrites.
    • "limit('5') throws" → cast at the edge; do not rely on the package's lack of strict_types.
    • "My text pattern stopped working" → the subclass overrode Select::$text_pattern; override getTextPattern() instead.
  • Closure-condition semantics need a short written explanation with the canonical example — reading-order filling under pre-allocated names is not obvious from the signature.

Scaling

  • Query throughput: dynamic generation cost is unchanged, and per-query placeholder bookkeeping remains negligible per statement but measurable when rendering thousands in tight loops. Beta2 adds literal/comment scanning per condition — benchmark reporting paths specifically rather than assuming parity with beta1.
  • Data scale: CTEs remain the meaningful win — hierarchical and graph queries as one statement instead of N round-trips or application-side recursion.
  • Connection behaviour: unchanged.

Failure Modes

Mode Trigger Detection Blast radius
Fatal on class load Adapter/subclass signature mismatch after upgrade Immediate, first autoload Total for affected paths
Override silently ignored Subclass overrode Select::$text_pattern (removed in beta2) None at build — wrong text pattern per dialect Silent, potentially wide
InvalidArgumentException on ?/value mismatch Placeholder count ≠ values after an edit At build Single request
Named-placeholder collision (LogicException) Same name reused across cols()/where()/having() At build Single request (500 if uncaught)
PDO parameter-count error at execute Generated value survived reset*() because a rendered union branch still spells it At execute Single request
Broken bind lookup getBindValues()[0] or bindValue(0, ...) after beta2 Test, or first wrong-value write Per call site
TypeError on scalar limit('abc'), or limit('5') under strict_types=1 At build Single request
Exception-handler over-capture catch (\LogicException) swallowing package errors In testing, if at all Potentially broad
Unbounded result set / SET clobbering Previously silent; closed in beta1 and still closed — Closed
Mixed ?/named statements, unbound ? on SQLite, corrupted $$...$$ on PostgreSQL Previously driver-rejected or silent; closed in beta2 — Closed

The dangerous shape has shifted. Beta1's headline risk was silent-wrong-answer becomes loud exception. Beta2 largely fixes that and introduces the opposite: $text_pattern is the one change that degrades silently, and numeric bind access is the one that fails as a plausible-looking wrong value rather than an error. Those two deserve explicit review attention; the loud exceptions do not.

Ramp-up

  • PHP 8.4 ramp precedes all package work; separate track, separate owner.
  • Developer learning curve: modest for basic use; steeper for the placeholder rules, the reset/union carve-out, and the composition-over-inheritance adapter pattern. Roughly one to two weeks for a Laravel-fluent developer, plus half a day of team knowledge-sharing on CTEs, bind-key opacity and closure-condition ordering.
  • Documentation: docs/upgrading.md is the primary artifact for 3.x→7.x; the beta1 and beta2 release notes are the authority for the beta deltas and must be read together. If any internal adapter documentation was written against beta1, mark it stale and re-review — beta2 invalidates the positional-bind guidance in it.
  • Review gates: no adapter code merges without static analysis at max level; an integration test proving the CTE path matches the legacy DB::raw() output; and a test covering a closure condition with mixed filled/unfilled ? placeholders.
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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast