How To Get The Raw SQL Query From Laravel's Query Builder?

Published October 12, 2024

Problem: Accessing Raw SQL from Laravel Query Builder

Laravel's Query Builder helps you create database queries. Sometimes, you need to see the raw SQL that the Query Builder makes. This can help with debugging, making queries faster, or using tools that need raw SQL.

Solution: Using the toSql() Method

Implementing toSql() for Raw SQL Retrieval

The toSql() method gets the raw SQL query from Laravel's Query Builder. This method returns the SQL string without running the query.

To use toSql(), add it to the end of your query chain:

$query = DB::table('users')->toSql();

This will return the SQL string that would run if you called get() or first() instead.

For example, DB::table('users')->toSql() returns:

select * from `users`

You can also use toSql() with more complex queries:

$query = DB::table('users')
    ->where('active', 1)
    ->whereIn('role', ['admin', 'moderator'])
    ->toSql();

This would return:

select * from `users` where `active` = ? and `role` in (?, ?)

Note that toSql() doesn't include the actual values for security reasons. It uses question marks as placeholders for the values.

Remember, toSql() only shows the SQL query. It doesn't run the query or return any data from the database. This makes it useful for checking your queries without changing your database.

Tip: Debugging with toSql()

When debugging complex queries, use toSql() along with the getBindings() method to see both the SQL structure and the actual values:

$query = DB::table('users')->where('active', 1)->whereIn('role', ['admin', 'moderator']);
$sql = $query->toSql();
$bindings = $query->getBindings();

dd($sql, $bindings);

This will display the SQL string and an array of the bound values, helping you understand exactly what query Laravel is generating.

Alternative Methods for SQL Query Extraction

Using DB::getQueryLog()

Laravel has a query logging feature that can help you get SQL queries executed during a request. Here's how to use it:

  1. Enable query logging at the start of your script or in a service provider:
DB::enableQueryLog();
  1. Run your database queries as usual.

  2. Get the log of all executed queries:

$queries = DB::getQueryLog();

This method returns an array of all queries, including the SQL, bindings, and execution time.

Note that query logging can affect performance, so use it only during development or debugging.

Tip: Optimize Query Logging

To reduce the performance impact of query logging, consider enabling it only for specific parts of your code:

DB::enableQueryLog();
// Your database queries here
$queries = DB::getQueryLog();
DB::disableQueryLog();

Implementing Event Listeners

Laravel also lets you capture SQL queries by setting up event listeners. This method gives you more control over when and how you capture queries. Here's how to do it:

  1. Create an event listener in your EventServiceProvider:
protected $listen = [
    'Illuminate\Database\Events\QueryExecuted' => [
        'App\Listeners\QueryExecutedListener',
    ],
];
  1. Create the listener class:
namespace App\Listeners;

use Illuminate\Database\Events\QueryExecuted;

class QueryExecutedListener
{
    public function handle(QueryExecuted $event)
    {
        $sql = $event->sql;
        $bindings = $event->bindings;
        $time = $event->time;

        // Log or process the query as needed
    }
}

This listener will capture every executed SQL query, allowing you to log or process them as needed.

Example: Selective Query Logging

You can modify the listener to log only specific queries:

public function handle(QueryExecuted $event)
{
    if (strpos($event->sql, 'users') !== false) {
        Log::info('User query executed:', [
            'sql' => $event->sql,
            'bindings' => $event->bindings,
            'time' => $event->time
        ]);
    }
}

This example logs only queries that contain the word 'users'.

Both methods provide ways to access raw SQL queries, but they capture all queries rather than just the one you're working on. Use these methods when you need to analyze multiple queries or when you can't modify the original query code.