How do I get the query builder to output its raw SQL query as a string?

943,397

Solution 1

To output to the screen the last queries ran you can use this:

DB::enableQueryLog(); // Enable query log

// Your Eloquent query executed by using get()

dd(DB::getQueryLog()); // Show results of log

I believe the most recent queries will be at the bottom of the array.

You will have something like that:

array(1) {
  [0]=>
  array(3) {
    ["query"]=>
    string(21) "select * from "users""
    ["bindings"]=>
    array(0) {
    }
    ["time"]=>
    string(4) "0.92"
  }
}

(Thanks to Joshua's comment below.)

Solution 2

Use the toSql() method on a QueryBuilder instance.

DB::table('users')->toSql() would return:

select * from `users`

This is easier than wiring up an event listener, and also lets you check what the query will actually look like at any point while you're building it.

Note: This method works for query builder or Eloquent, however toSql() is used instead of first() or get(). You cannot run the query and also get the SQL at the same time using this method.

Solution 3

DB::QueryLog() works only after you execute the query using $builder->get().

If you want to get the raw query before or without executing the query, you can use the $builder->toSql() method.

Example to get the raw SQL and to replace '?' with actual binding values:

$query = str_replace(array('?'), array('\'%s\''), $builder->toSql());
$query = vsprintf($query, $builder->getBindings());
dump($query);

$result = $builder->get();

Or you can deliberately trigger an error, for example, by using a non-existent table or column. Then you can see the generated query in the exception message.

Solution 4

You can listen to the 'illuminate.query' event. Before the query add the following event listener:

Event::listen('illuminate.query', function($query, $params, $time, $conn) 
{ 
    dd(array($query, $params, $time, $conn));
});

DB::table('users')->get();

This will print out something like:

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}

Solution 5

If you are trying to get the Log using Illuminate without Laravel use:

\Illuminate\Database\Capsule\Manager::getQueryLog();

You could also nock up a quick function like so:

function logger()
{
    $queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
    $formattedQueries = [];
    foreach ($queries as $query) :
        $prep = $query['query'];

        foreach ($query['bindings'] as $binding) :

            if (is_bool($binding)) {
                $val = $binding === true ? 'TRUE' : 'FALSE';
            } else if (is_numeric($binding)) {
                $val = $binding;
            } else {
                $val = "'$binding'";
            }

            $prep = preg_replace("#\?#", $val, $prep, 1);
        endforeach;
        $formattedQueries[] = $prep;
    endforeach;
    return $formattedQueries;
}

EDIT

updated versions seem to have query logging disabled by default (the above returns an empty array). To turn back on, when initialising the Capsule Manager, grab an instance of the connection and call the enableQueryLog method

$capsule::connection()->enableQueryLog();

EDIT AGAIN

Taking the actual question into consideration, you could actually do the following to convert the current single query instead of all previous queries:

$sql = $query->toSql();
$bindings = $query->getBindings();
Share:
943,397
meiryo
Author by

meiryo

Updated on July 08, 2022

Comments

  • meiryo
    meiryo almost 2 years

    Given the following code:

    DB::table('users')->get();
    

    I want to get the raw SQL query string that the database query builder above will generate. In this example, it would be SELECT * FROM users.

    How do I do this?