Question
Given the following Laravel query builder code:
DB::table('users')->get();
I want to inspect the raw SQL query string that this builder generates. In this example, I expect something like:
SELECT * FROM users
How can I get the SQL string from a Laravel query builder query?
Short Answer
By the end of this page, you will understand how Laravel's query builder builds SQL, how to get the SQL template using toSql(), how parameter bindings work, and how developers typically debug and inspect queries in real Laravel projects.
Concept
Laravel's query builder does not immediately run SQL when you start chaining methods like table(), where(), or orderBy(). Instead, it builds a query object step by step.
When you finally call methods like get(), first(), insert(), update(), or delete(), Laravel compiles that query object into SQL and sends it to the database.
To inspect the SQL before execution, Laravel provides:
toSql()— returns the SQL string with placeholders such as?getBindings()— returns the values that will be inserted into those placeholders
This matters because in real development you often need to:
- debug a query that is not returning expected results
- verify filters and joins
- optimize performance
- log generated SQL
- compare what Laravel builds against handwritten SQL
A key detail: the SQL returned by toSql() is usually a prepared statement template, not a fully interpolated final SQL string. That means values are often shown as ? placeholders instead of being inserted directly into the string.
Mental Model
Think of the query builder like filling out a restaurant order form.
DB::table('users')chooses the menu sectionwhere(...)adds conditions to the orderorderBy(...)adds sorting instructionstoSql()shows the printed order ticket templategetBindings()shows the actual values that will be attached to that ticketget()sends the order to the kitchen
So toSql() shows the structure of the query, while getBindings() shows the data that will be plugged into it.
Syntax and Examples
Basic syntax
Use toSql() on the builder before executing it:
$sql = DB::table('users')->toSql();
echo $sql;
Output:
select * from `users`
Depending on your database driver, quoting may vary. For example, MySQL often uses backticks.
Important: do not call get() first
This will not work the way you expect:
DB::table('users')->get()->toSql();
Why? Because get() executes the query and returns a collection, not a query builder.
Query with bindings
$query = DB::table('users')->where(, );
= ->();
= ->();
();
();
Step by Step Execution
Consider this example:
$query = DB::table('users')
->where('active', 1)
->orderBy('name');
dd($query->toSql(), $query->getBindings());
Step 1: DB::table('users')
Laravel creates a query builder for the users table.
Step 2: where('active', 1)
Laravel adds a filter condition.
At this point, the builder knows:
- the table is
users - there is a
whereclause onactive - the value
1is stored as a binding
Step 3: orderBy('name')
Laravel adds sorting to the query definition.
Step 4:
Real World Use Cases
Developers inspect raw SQL in Laravel for many practical reasons:
Debugging incorrect results
If a query returns too many or too few rows, checking the SQL helps confirm whether the conditions were built correctly.
Performance tuning
You may want to copy the SQL into your database client and run EXPLAIN to inspect indexes and query cost.
Logging slow queries
Applications often log generated SQL during development or when investigating production issues.
Verifying dynamic filters
If your app builds queries from request parameters, inspecting SQL helps confirm that optional filters are applied correctly.
Learning SQL through Laravel
Beginners often use toSql() to connect Laravel query builder syntax to the actual SQL being sent to the database.
Real Codebase Usage
In real Laravel projects, developers usually inspect queries using a few common patterns.
1. Inspect before execution
$query = DB::table('users')->where('role', 'admin');
dd($query->toSql(), $query->getBindings());
This is the simplest pattern when debugging one query.
2. Reuse the builder
$query = DB::table('users')->where('active', 1);
logger()->debug($query->toSql(), $query->getBindings());
$users = $query->get();
Store the builder in a variable so you can inspect it and then execute it.
3. Listen to all queries
Laravel can listen for every query executed during a request:
Common Mistakes
Calling toSql() after get()
Broken code:
DB::table('users')->get()->toSql();
Problem:
get()returns a collection of results- collections do not have the same query-builder methods
Fix:
DB::table('users')->toSql();
Expecting bound values inside toSql()
Broken expectation:
$query = DB::table('users')->where('id', 5);
echo $query->toSql();
You may expect:
select `users` `id`
Comparisons
| Tool | What it returns | Executes query? | Best use |
|---|---|---|---|
toSql() | SQL template with ? placeholders | No | Inspect query structure |
getBindings() | Bound parameter values | No | Inspect values sent with query |
get() | Result rows | Yes | Fetch data |
dd($query->toSql(), $query->getBindings()) | SQL + bindings dump | No | Quick debugging |
DB::listen() | Every executed query with time and bindings |
Cheat Sheet
// Get SQL template
$sql = DB::table('users')->toSql();
// Get bindings
$bindings = DB::table('users')->where('id', 1)->getBindings();
// Debug both
$query = DB::table('users')->where('id', 1);
dd($query->toSql(), $query->getBindings());
// Execute after inspection
$query = DB::table('users')->where('active', 1);
$users = $query->get();
// Listen to all queries
DB::listen(function ($query) {
logger($query->sql, $query->bindings);
});
Rules to remember
FAQ
How do I print the SQL query in Laravel?
Use toSql() on the query builder:
echo DB::table('users')->toSql();
Why does Laravel show ? instead of actual values?
Laravel uses prepared statements. The SQL and the values are stored separately for safety and performance.
How do I see the values for the placeholders?
Use getBindings():
$query = DB::table('users')->where('id', 10);
dd($query->toSql(), $query->getBindings());
Can I use toSql() with Eloquent?
Yes.
User::where('active', 1)->();
Mini Project
Description
Build a small Laravel debugging snippet that creates a filtered user query and inspects the generated SQL before executing it. This demonstrates the difference between the query builder itself, the SQL template, and the actual bindings.
Goal
Create and inspect a query using toSql() and getBindings(), then execute it to retrieve results.
Requirements
- Create a query for the
userstable. - Add at least one
wherecondition and oneorderByclause. - Output the SQL template.
- Output the bindings.
- Execute the query and store the results.
Keep learning
Related questions
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.
Convert a PHP Object to an Associative Array
Learn how to convert a PHP object to an associative array, including quick methods, recursion, pitfalls, and practical examples.
Convert a Postman Request to cURL and PHP cURL
Learn how to convert a Postman POST request into a cURL command and use the same request in PHP cURL with headers and body.