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

To Raw Sql Laravel Package

pyaesoneaung/to-raw-sql

Inspect the SQL behind your Laravel query builder and Eloquent queries. to-raw-sql converts builders into readable raw SQL strings, making debugging, logging, and optimization simple. A lightweight helper with a clean API for development.

View on GitHub
Deep Wiki
Context7

Getting Started

Install it the usual way — the service provider is auto-discovered, so there is no config file to publish and nothing to register in config/app.php:

composer require pyaesoneaung/to-raw-sql

The package registers a toRawSql() macro on both Illuminate\Database\Query\Builder and Illuminate\Database\Eloquent\Builder, so the first thing to do is open php artisan tinker and call it on a query you already know the answer to:

User::where('active', true)->where('created_at', '>', now()->subWeek())->toRawSql();
// select * from `users` where `active` = 1 and `created_at` > '2024-01-01 00:00:00'

That is the entire mental model: toSql() gives you the statement with ? placeholders, toRawSql() gives you the same statement with the bindings substituted in, exactly as the driver would see it. The first real use case is debugging a query that "should work" — a whereIn with an empty array, a mis-ordered orWhere group, a date boundary — where seeing the interpolated values removes all ambiguity.

Look first at the package's service provider (it is a handful of lines) to confirm which builder classes get the macro, then verify against your Laravel version before you build habits around it — see the Gotchas section.

Implementation Patterns

Debugging in place. The highest-value pattern is dropping toRawSql() next to an existing dump()/dd() chain while you are chasing a bug, then removing it. Because it is non-executing, it is safe to call on a builder you are about to run:

$query = Order::where('status', 'paid')->whereBetween('total', [$min, $max]);
logger()->debug($query->toRawSql());
$orders = $query->paginate(25); // builder is untouched

Logging the SQL of slow or suspicious code paths. Wrap it in a tiny helper rather than sprinkling toRawSql() everywhere, so you can strip it out later:

function sql_of($query): string
{
    return $query->toRawSql();
}

This is genuinely useful inside queue jobs and console commands, where you cannot dd() and where the actual query only runs inside a transaction you would rather not break.

Reproducing a bug for a DBA or another developer. Because the output is a copy-pasteable statement, it is the fastest way to hand a query to someone with a MySQL client open. Pair it with ->toSql()/->getBindings() when the other party needs the parameterised form (some DBAs prefer that for EXPLAIN):

[$sql, $bindings] = [$query->toSql(), $query->getBindings()];

In tests, as a readable failure message. When an assertion about a dataset fails, dumping the raw SQL of the query under test is often faster than reading the stack trace:

$this->assertSame(3, $query->count(), $query->toRawSql());

Note that the third argument is only evaluated on failure in most assertion helpers, but toRawSql() is cheap enough that the eager form is fine here.

Admin/debug panels behind a gate. If you have an internal "query inspector" screen (Horizon-adjacent tooling, an artisan command, a dev-only route), wrap the call so it never leaks into production:

if (app()->isLocal()) {
    dump($query->toRawSql());
}

Works across both builders. DB::table('users')->where(...)->toRawSql() and the Eloquent equivalent behave the same, so it is useful when you are rewriting a query-builder call into Eloquent (or vice versa) and want to prove the two produce the same SQL.

Gotchas and Tips

  • Laravel 10.15+ has toRawSql() natively. If you are on a recent Laravel, this package is redundant — the framework's Illuminate\Database\Query\Builder::toRawSql() does the same job and handles binding substitution more robustly. Check Builder::hasMacro('toRawSql') or just try the call without the package installed before adding a dependency. This is the single biggest reason the package is a hard sell on new projects; it is realistically a tool for Laravel 8/9 codebases or legacy apps pinned below 10.15.
  • Last release was July 2023, so do not expect fixes for newer grammar features (JSON path operators, whereJsonContains variations, new where* methods added since). Test the specific query shape you depend on. Dependents count is effectively zero, which tells you the community has moved to the native method.
  • Placeholder substitution is textual, not semantic. A literal ? inside a raw fragment will corrupt the output: whereRaw("name LIKE '%?%'") or a whereRaw with a ? inside a quoted string will have the wrong binding spliced in. The same applies to ?? in some grammars. If your query uses whereRaw with inline literals, verify the output by eye before trusting it.
  • Bindings are interpolated, not escaped for you. Values containing single quotes, backslashes, or binary data will produce SQL that is representative but not necessarily executable when pasted into a client. Treat the output as a debugging aid, not as a string to DB::select().
  • Date bindings depend on the grammar. Carbon instances are formatted by the connection's grammar; if you are comparing against a query run on a different connection, the timestamps may not match what you expect.
  • Call it before the terminal method. get(), first(), paginate(), count() all execute. toRawSql() must be called on the builder before those, and it does not execute anything itself — it is a pure read of toSql() plus bindings.
  • Redact before logging. The whole point is to show values, which means emails, tokens, and PII end up in your log files and in Sentry. Never wire toRawSql() into a global DB::listen or exception handler without a redaction step. For production observability, prefer DB::listen() with QueryExecuted and a binding scrubber.
  • It overrides nothing you should rely on. If you need different formatting (e.g. multi-line, or preserving ? for a prepared statement viewer), define your own macro under a different name — do not shadow toRawSql, because a future Laravel upgrade will collide with it.
  • Extension point is the macro itself. There is no config, no driver abstraction, no events. If you need per-connection behaviour (Postgres $1 placeholders, MySQL backticks), you will be writing your own macro; this package only covers the default grammar path.
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.
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
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core