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

Eloquent Dumper Laravel Package

recca0120/eloquent-dumper

Eloquent Dumper adds dump() and dd() helpers to Laravel's Eloquent query builder so you can instantly inspect the generated SQL with its bindings while debugging. No query log setup needed—just chain it onto any query. Works with Eloquent models and the query builder.

View on GitHub
Deep Wiki
Context7

Getting Started

Install as a dev-only dependency. This is a debugging aid, not runtime infrastructure — it belongs in require-dev so it cannot be autoloaded in production:

composer require --dev recca0120/eloquent-dumper

Confirm auto-discovery. Check composer.json in the package for a extra.laravel.providers entry. With a single-maintainer package of this size, the integration surface is usually either a service provider that registers a query-builder macro, or a trait you add to a model. That distinction determines whether it works on DB::table(...) chains as well as Eloquent models. If no provider is auto-discovered on Laravel 11+, register it in bootstrap/providers.php; on Laravel ≤10, in config/app.php.

Where to look first, in this order:

  1. README.md usage section — get the exact method name. Packages in this niche variously use dumpSql, ddSql, or dumpQuery; do not guess, because a wrong method name on a builder throws BadMethodCallException and looks like an install failure.
  2. composer.json require block — the illuminate/* and PHP version constraints are the single biggest adoption risk here. A package last released 2024-03-12 may pin illuminate/support: ^9|^10 and quietly block a Laravel 11/12 upgrade.
  3. src/ — find the macro registration and whether it wraps Symfony VarDumper (dump()) or PHP var_dump. That tells you whether output is readable in Tinker vs. only in the browser.

First use case. The canonical win is replacing the two-step ritual you already do by hand:

// Before: two calls, easy to desync
$q = User::where('active', 1)->whereHas('posts', fn ($p) => $p->where('published', 1));
dump($q->toSql(), $q->getBindings());

// After: one call, SQL + bindings shown together in order
User::where('active', 1)
    ->whereHas('posts', fn ($p) => $p->where('published', 1))
    ->dumpSql();

Run it in php artisan tinker against a real model. If the output shows the where exists (select ...) subquery with its bindings aligned to the placeholders, the package is working and you can stop reading.

Do this before committing to it: on Laravel 10.15+ the framework already ships ->toRawSql() and ->ddRawSql() on the query builder, which interpolate bindings into the SQL string. Try those first. If they cover your need, you do not need this dependency at all — see the Gotchas section for the comparison.

Implementation Patterns

Pattern 1 — Chained inspection without breaking the chain. If the dump method returns $this (most do), insert it mid-chain to see what each stage contributes:

$query = Order::query()
    ->where('status', 'open')
    ->dumpSql()                      // just the status filter
    ->whereBetween('created_at', [$from, $to])
    ->dumpSql()                      // narrow range + bindings
    ->with('customer');

This is the workflow the package is actually built for: verifying that a when() conditional actually fired and that its bindings landed in the right positional slot.

Pattern 2 — Isolating a scope or relationship. Scopes are where SQL surprises hide, because apply() merges constraints you did not write in front of you. Call the scope on a fresh builder, dump, and read the where clauses:

$query = Invoice::query()->active()->forTenant($id);   // unknown internals
$query->dumpSql();                                     // see the real WHERE tree

Same trick for whereHas/withCount: the subquery SQL and its bindings are the thing you cannot eyeball from the PHP.

Pattern 3 — Debugging a controller without a profiler. For an isolated broken endpoint on a local environment, drop a dump call into the controller, hit the route, and read the full query in the response. This is faster than installing Debugbar or Telescope for a one-off, and it works in a JSON API where the response is otherwise opaque. Remove it before committing.

Pattern 4 — Assertions in feature tests. Rather than whereRaw guessing, snapshot the generated SQL in a test to catch a regression in a scope:

$sql = Order::query()->pending()->toSql();

$this->assertStringContainsString('"status" = ?', $sql);

Note this uses toSql() — the package's value in tests is mostly that its dump output tells you what string to assert against, not that you assert on the dump itself. Do not build test assertions on dumped output; the format is not a stable contract.

Pattern 5 — Whole-request view with DB::listen. The package is per-builder. If you need to know what a request issued across many builders (including lazy loads), pair it with the framework's own listener and use the dumper to inspect individual queries that look wrong:

DB::listen(fn ($q) => logger()->debug($q->sql, $q->bindings));

Pattern 6 — Copying a query out. To paste into a SQL client or EXPLAIN, you need interpolated SQL, not ? placeholders. Take the dumped SQL + bindings and interpolate, or prefer ->toRawSql() where available. This is the most common real workflow: dump → copy → EXPLAIN → fix the missing index → come back. Budget for the interpolation step; the package gives you the ingredients, not the final paste-ready string.

Where this fits vs. alternatives. Use the dumper for one query, right now, in the request path. Use Debugbar for a session of browsing. Use Telescope for after-the-fact "what did that request actually run". Use EXPLAIN for performance. The package is the smallest tool in that set and should stay that way — reach for it when you want a zero-setup answer, not when you want a dashboard.

Gotchas and Tips

Bindings are listed, not embedded — the #1 confusion. You get select * from users where status = ? plus [1] separately. Pasting the SQL alone into a client fails on the ?. Some packages interpolate, some do not; check the output before assuming. If interpolation is what you want and you are on Laravel ≥10.15, native ->toRawSql() does exactly that and is one less dependency to maintain.

Dumping does not execute the query. You see SQL and bindings, never a result set, never a row count, never an error from the database. A syntactically wrong query dumps perfectly. Always follow a dump with a real ->get() or ->count() before concluding the query is correct.

toSql() semantics bite after execution. Once you call ->get(), you have a Collection, and the dump method is not on it. Dump before the terminal method. Similarly, paginate() runs a count(*) under the hood that you will not see in a single dump — if your paginated query is slow, the dumper will mislead you into blaming the main query.

This does not find N+1 problems. It inspects one builder in isolation. Lazy loading generates queries you never called the dumper on. For N+1, use Model::preventLazyLoading() in a local service provider or Debugbar's timeline — do not look for it here.

Macros are global and can collide. Query-builder macros live on the builder for the whole process. Two debugging packages registering the same method name means whichever boots last wins, silently. If the method "is not a function" in one project and works in another, check provider order and whether another dev dependency is shadowing it.

Binding values are not always scalars. Carbon, DateTime, enums with casts, and backed enum instances can appear in the bindings list. The dumped representation may be verbose or, for enums, unhelpful — remember the database receives the stringified form, so a binding that dumps as an object is a hint you are missing a cast or a ->format().

Keep it out of production, twice over. require-dev protects the autoloader, but a leftover ->ddSql() in a controller is a hard 500 (or a leaked schema) in any environment. If you want a belt-and-braces guard, wrap your own snippet macro that no-ops unless app()->environment('local') — and grep for the package's method names before every merge to main.

Pin the version and watch the maintenance signal. 29 stars, a single maintainer, last release March 2024. The realistic risk is not a bug — it is that the package stops resolving when you upgrade Laravel. Pin it ("recca0120/eloquent-dumper": "1.*" or the exact tag) and treat a failed composer update here as a signal to delete the dependency, not to patch around it. The fallback is one line of framework code:

dump($query->toRawSql());   // Laravel >= 10.15

Extension points are thin, by design. There is likely no publishable config and nothing to bind in the container. If you need shared behaviour — e.g. "always dump to the log rather than the response in a queued job" — write your own macro that calls toRawSql() or DB::listen, rather than trying to configure this package into it. Forking a 29-star debug helper for customization is not a good trade.

Ramp-up is genuinely an hour, not a day. Install, read one README section, run one Tinker line. The evaluation cost here is not learning the API; it is the ten minutes spent confirming your Laravel and PHP versions are inside composer.json's constraints. Do that check first — if the spike opens with a dependency-resolution conflict, the rest of the assessment is moot.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager