Jak sprawić, by konstruktor zapytań wypuścił swoje surowe zapytanie SQL jako ciąg znaków?

Podano następujący kod:

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

Chcę uzyskać surowy ciąg zapytania SQL, który wygeneruje powyższy konstruktor zapytań, więc w tym przykładzie będzie to SELECT * FROM users.

Jak mam to zrobić?
Author: mega6382, 2013-08-14

23 answers

Do wyświetlenia na ekranie ostatnich zapytań możesz użyć tego

dd(DB::getQueryLog());

Wierzę, że ostatnie zapytania będą na dole tablicy.

Będziesz miał coś takiego:

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

Zgodnie z komentarzem Joshuy poniżej, to jest teraz domyślnie wyłączone. Aby użyć, musisz włączyć go ręcznie za pomocą:

DB::enableQueryLog();
 377
Author: jfortunato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:03

Użyj metody toSql() Na wystąpieniu QueryBuilder.

DB::table('users')->toSql() zwraca:

Select * from 'users'

Jest to łatwiejsze niż podłączenie słuchacza zdarzeń, a także pozwala sprawdzić, jak faktycznie będzie wyglądało zapytanie w dowolnym momencie podczas jego budowania.

 525
Author: Steven Mercatante,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-03 03:57:27

Możesz posłuchać ' illuminate.zapytanie " event. Przed zapytaniem Dodaj następujący detektor zdarzeń:

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

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

To wydrukuje coś w stylu:

array(4) {
  [0]=>
  string(21) "select * from "users""
  [1]=>
  array(0) {
  }
  [2]=>
  string(4) "0.94"
  [3]=>
  string(6) "sqlite"
}
 50
Author: Rubens Mariuzzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-14 16:14:58

Jeśli próbujesz uzyskać Log za pomocą Illuminate bez użycia Laravela:

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

Można też wstawić taką szybką funkcję:

function logger() {
    $queries = \Illuminate\Database\Capsule\Manager::getQueryLog();
    $formattedQueries = [];
    foreach( $queries as $query ) :
        $prep = $query['query'];
        foreach( $query['bindings'] as $binding ) :
            $prep = preg_replace("#\?#", is_numeric($binding) ? $binding : "'" . $binding . "'", $prep, 1);
        endforeach;
        $formattedQueries[] = $prep;
    endforeach;
    return $formattedQueries;
}

EDIT

Zaktualizowane wersje wydają się mieć domyślnie wyłączone rejestrowanie zapytań (powyższe zwraca pustą tablicę). Aby włączyć ponownie, podczas inicjalizacji Menedżera kapsułek, chwyć instancję połączenia i wywołaj metodę enableQueryLog

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

EDIT AGAIN

Biorąc rzeczywiste pytanie do aby przekonwertować bieżące pojedyncze zapytanie zamiast wszystkich poprzednich, możesz wykonać następujące czynności:

$sql = $query->toSql();
$bindings = $query->getBindings();
 39
Author: Luke Snowden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 17:10:34

DB::QueryLog() działa tylko po wykonaniu zapytania $builder->get(). jeśli chcesz uzyskać zapytanie przed jego wykonaniem, możesz użyć metody $builder->toSql(). to jest przykład, jak uzyskać sql i powiązać go:

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

    $result = $builder->get();
 34
Author: Kakashi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-20 11:59:53

Istnieje metoda w eloquent do uzyskania ciągu zapytania.

ToSql()

W naszym przypadku,

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

Return

select * from users

Jest dokładnym rozwiązaniem, które zwraca ciąg zapytania SQL..Mam nadzieję, że to pomoże...

 31
Author: CelinVeronicca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 11:05:41
$data = User::toSql();
echo $data; //this will retrun select * from users. //here User is model
 22
Author: Kuldeep Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-25 08:38:15

Jeśli używasz laravel 5.1 i MySQL możesz użyć tej funkcji wykonanej przeze mnie:

/*
 *  returns SQL with values in it
 */
function getSql($model)
{
    $replace = function ($sql, $bindings)
    {
        $needle = '?';
        foreach ($bindings as $replace){
            $pos = strpos($sql, $needle);
            if ($pos !== false) {
                if (gettype($replace) === "string") {
                     $replace = ' "'.addslashes($replace).'" ';
                }
                $sql = substr_replace($sql, $replace, $pos, strlen($needle));
            }
        }
        return $sql;
    };
    $sql = $replace($model->toSql(), $model->getBindings());

    return $sql;
}

Jako parametr wejściowy możesz użyć jednego z tych

Illuminate\Database\Eloquent\Builder

Illuminate\Database\Eloquent\Relations\HasMany

Illuminate\Database\Query\Builder

 20
Author: Yevgeniy Afanasyev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 23:45:31

Pierwsza droga:

Po prostu możesz zrobić następujące rzeczy za pomocą toSql() metoda,

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

echo $query->toSql();

Jeśli to nie działa, możesz skonfigurować to z dokumentacji Laravela.

Druga droga:

Innym sposobem jest

DB::getQueryLog()

Ale jeśli zwraca pustą tablicę to domyślnie jest wyłączona odwiedź to ,

Wystarczy włączyć z DB::enableQueryLog() i będzie działać:)

Aby uzyskać więcej informacji odwiedź Github Issue aby dowiedzieć się więcej na ten temat.

Mam nadzieję, że pomoże:)

 8
Author: Sagar Naliyapara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 05:45:00

Od laravel 5.2 i dalej. możesz użyć DB::listen, aby uzyskać wykonywane zapytania.

DB::listen(function ($query) {
    // $query->sql
    // $query->bindings
    // $query->time
});

Lub jeśli chcesz debugować pojedynczą instancję Builder, możesz użyć metody toSql.

DB::table('posts')->toSql(); 
 6
Author: Zayn Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-02 17:01:59

To jest funkcja, którą umieściłem w mojej klasie modeli bazowych. Po prostu przekaż obiekt Query builder do niego, a łańcuch SQL zostanie zwrócony.

function getSQL($builder) {
  $sql = $builder->toSql();
  foreach ( $builder->getBindings() as $binding ) {
    $value = is_numeric($binding) ? $binding : "'".$binding."'";
    $sql = preg_replace('/\?/', $value, $sql, 1);
  }
  return $sql;
}
 4
Author: BoogieBug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-28 08:59:41

Dla laravel 5.5.X

Jeśli chcesz otrzymywać każde zapytanie SQL wykonane przez Twoją aplikację, możesz użyć metody listen. Ta metoda jest przydatna do rejestrowania zapytań lub debugowania. Możesz zarejestrować swoje zapytanie w usługodawcy:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

Źródło

 4
Author: scre_www,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-06 09:53:20

Aby zobaczyć wykonane zapytanie Laravel użyj dziennika zapytań laravel

DB::enableQueryLog();

$queries = DB::getQueryLog();
 4
Author: Jasim Juwel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-21 05:37:49

Najpierw musisz włączyć dziennik zapytań, wywołując:

DB::enableQueryLog();

Po zapytaniach wykorzystujących fasadę DB można napisać:

dd(DB::getQueryLog());

Wyjście będzie takie jak poniżej:

array:1 [▼
  0 => array:3 [▼
    "query" => "select * from `users` left join `website_user` on `users`.`id` = `website_user`.`user_id` left join `region_user` on `users`.`id` = `region_user`.`user_id` left ▶"
    "bindings" => array:5 [▶]
    "time" => 3.79
  ]
]

Blockquote

 4
Author: Ravi Mane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-31 04:29:41

Composer require "barryvdh / laravel-debugbar": "2.3.*"

Zobaczysz Tutaj wpisz opis obrazka

 3
Author: 潘庆强,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 08:09:28

Możesz użyć tego pakietu, aby uzyskać wszystkie zapytania, które są wykonywane podczas ładowania strony

https://github.com/barryvdh/laravel-debugbar
 2
Author: Lucky Saini,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-14 14:01:26

Jeśli nie używasz Laravel, ale używasz Eloquent package to:

use \Illuminate\Database\Capsule\Manager as Capsule;
use \Illuminate\Events\Dispatcher;
use \Illuminate\Container\Container;

$capsule = new Capsule;

$capsule->addConnection([
    // connection details
]);
// Set the event dispatcher used by Eloquent models... (optional)
$capsule->setEventDispatcher(new Dispatcher(new Container));

// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();

// Setup the Eloquent ORM...(optional unless you've used setEventDispatcher())
$capsule->bootEloquent();

// Listen for Query Events for Debug
$events = new Dispatcher;
$events->listen('illuminate.query', function($query, $bindings, $time, $name)
{
    // Format binding data for sql insertion
    foreach ($bindings as $i => $binding) {
        if ($binding instanceof \DateTime) {
            $bindings[$i] = $binding->format('\'Y-m-d H:i:s\'');
        } else if (is_string($binding)) {
            $bindings[$i] = "'$binding'";`enter code here`
        }
    }

    // Insert bindings into query
    $query = str_replace(array('%', '?'), array('%%', '%s'), $query);
    $query = vsprintf($query, $bindings);

    // Debug SQL queries
    echo 'SQL: [' . $query . ']';
});

$capsule->setEventDispatcher($events);
 2
Author: Salman Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-24 09:29:02

Możesz użyć clockwork

Clockwork to rozszerzenie Chrome do programowania PHP, rozszerzające narzędzia programistyczne o nowy panel dostarczający wszelkiego rodzaju informacje przydatne do debugowania i profilowania aplikacji PHP, w tym informacje o żądaniach, nagłówkach, danych get I post, plikach Cookie, danych sesji, zapytaniach do bazy danych, trasach, wizualizacji czasu pracy aplikacji i innych.

Ale działa również w Firefoksie

 2
Author: wdog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-11 16:39:03

Stworzyłem kilka prostych funkcji, aby uzyskać sql i wiązania z niektórych zapytań.

/**
 * getSql
 *
 * Usage:
 * getSql( DB::table("users") )
 * 
 * Get the current SQL and bindings
 * 
 * @param  mixed  $query  Relation / Eloquent Builder / Query Builder
 * @return array          Array with sql and bindings or else false
 */
function getSql($query)
{
    if( $query instanceof Illuminate\Database\Eloquent\Relations\Relation )
    {
        $query = $query->getBaseQuery();
    }

    if( $query instanceof Illuminate\Database\Eloquent\Builder )
    {
        $query = $query->getQuery();
    }

    if( $query instanceof Illuminate\Database\Query\Builder )
    {
        return [ 'query' => $query->toSql(), 'bindings' => $query->getBindings() ];
    }

    return false;
}

/**
 * logQuery
 *
 * Get the SQL from a query in a closure
 *
 * Usage:
 * logQueries(function() {
 *     return User::first()->applications;
 * });
 * 
 * @param  closure $callback              function to call some queries in
 * @return Illuminate\Support\Collection  Collection of queries
 */
function logQueries(closure $callback) 
{
    // check if query logging is enabled
    $logging = DB::logging();

    // Get number of queries
    $numberOfQueries = count(DB::getQueryLog());

    // if logging not enabled, temporarily enable it
    if( !$logging ) DB::enableQueryLog();

    $query = $callback();

    $lastQuery = getSql($query);

    // Get querylog
    $queries = new Illuminate\Support\Collection( DB::getQueryLog() );

    // calculate the number of queries done in callback
    $queryCount = $queries->count() - $numberOfQueries;

    // Get last queries
    $lastQueries = $queries->take(-$queryCount);

    // disable query logging
    if( !$logging ) DB::disableQueryLog();

    // if callback returns a builder object, return the sql and bindings of it
    if( $lastQuery )
    {
        $lastQueries->push($lastQuery);
    }

    return $lastQueries;
}

Użycie:

getSql( DB::table('users') );
// returns 
// [
//     "sql" => "select * from `users`",
//     "bindings" => [],
// ]

getSql( $project->rooms() );
// returns
// [
//     "sql" => "select * from `rooms` where `rooms`.`project_id` = ? and `rooms`.`project_id` is not null",
//     "bindings" => [ 7 ],
// ]
 2
Author: blablabla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-01 10:55:18

Najprostszym sposobem jest popełnienie celowego błędu . Na przykład Chcę zobaczyć pełne zapytanie SQL następującej relacji:

 public function jobs()
        {
            return $this->belongsToMany(Job::class, 'eqtype_jobs')
                   ->withPivot(['created_at','updated_at','id'])
                   ->orderBy('pivot_created_at','desc');
        }

Po prostu aby kolumna nie została znaleziona, tutaj wybieram created_at i zmieniłem ją na created_ats przez dodanie s na:

public function jobs()
            {
                return $this->belongsToMany(Job::class, 'eqtype_jobs')
                       ->withPivot(['created_ats','updated_at','id'])
                       ->orderBy('pivot_created_at','desc');
            }

Więc debuger zwróci następujący błąd:

(4/4) ErrorException SQLSTATE [42S22]: Column not found: 1054 Unknown kolumna " eqtype_jobs.created_ats ' in 'field list' (SQL: wybierz jobs.*, eqtype_jobs.set_id jako pivot_set_id, eqtype_jobs.job_id jako pivot_job_id, eqtype_jobs.created_ats jako pivot_created_ats, eqtype_jobs.updated_at jako pivot_updated_at, eqtype_jobs.id as pivot_id from jobs inner dołącz do eqtype_jobs na jobs.id = eqtype_jobs.job_id gdzie eqtype_jobs.set_id = 56 order by pivot_created_at DESC limit 20 offset 0) (widok: / home / said / www/factory/resources/views/set / show.blade.php)

Powyższy komunikat o błędzie zwraca pełne zapytanie SQL z błędem

SQL: select  jobs.*, eqtype_jobs.set_id as pivot_set_id,  eqtype_jobs.job_id as pivot_job_id, eqtype_jobs.created_ats as pivot_created_ats, eqtype_jobs.updated_at as  pivot_updated_at, eqtype_jobs.id as pivot_id from jobs inner join eqtype_jobs on jobs.id = eqtype_jobs.job_id where  eqtype_jobs.set_id = 56 order by pivot_created_at desc limit 20 offset 0

Teraz po prostu usuń dodatkowe s z created_at i przetestuj ten SQL, jak chcesz w dowolnym edytorze SQL, takim jak phpMyAdmin edytor SQL!

Notice:

Roztwór został przetestowany za pomocą Laravel 5.4.

 1
Author: SaidbakR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 19:34:12

Oto rozwiązanie, którego używam:

DB::listen(function ($sql, $bindings, $time) {
    $bound = preg_replace_callback("/\?/", function($matches) use ($bindings) {
        static $localBindings;
        if (!isset($localBindings)) {
            $localBindings = $bindings;
        }
        $val = array_shift($localBindings);

        switch (gettype($val)) {
            case "boolean":
                $val = ($val === TRUE) ? 1 : 0;  // mysql doesn't support BOOL data types, ints are widely used
                // $val = ($val === TRUE) ? "'t'" : "'f'";   // todo: use this line instead of the above for postgres and others
                break;

            case "NULL":
                $val = "NULL";
                break;

            case "string":
            case "object":
                $val = "'". addslashes($val). "'";   // correct escaping would depend on the RDBMS
                break;
        }
        return $val;
    }, $sql);
    array_map(function($x) { 
        (new \Illuminate\Support\Debug\Dumper)->dump($x); 
    }, [$sql, $bindings, $bound]);
});

Proszę przeczytać komentarze w kodzie. Wiem, że nie jest idealny, ale dla mojego codziennego debugowania jest OK. Próbuje zbudować związane zapytanie z większą lub mniejszą niezawodnością. Jednak nie ufaj mu całkowicie, silniki bazodanowe inaczej uciekają od wartości, których ta krótka funkcja nie implementuje. Więc weź wynik ostrożnie.

 0
Author: Csongor Halmai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-05 07:55:43

Drukuj Ostatnie zapytanie

DB::enableQueryLog();

$query        = DB::getQueryLog();
$lastQuery    = end($query);
print_r($lastQuery);
 0
Author: Sohomdeep Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-01 07:18:12

Tak bardzo jak kocham ten framework, nienawidzę kiedy zachowuje się jak gówno.

DB::enableQueryLog() jest całkowicie bezużyteczny. DB::listen jest równie bezużyteczny. Pokazała część zapytania, kiedy powiedziałem $query->count(), ale jeśli zrobię $query->get(), nie ma nic do powiedzenia.

Jedynym rozwiązaniem, które wydaje się działać konsekwentnie, jest celowe umieszczenie niektórych błędów składni lub innych w parametrach ORM, takich jak nieistniejąca nazwa kolumny/tabeli, uruchomienie kodu w linii poleceń podczas trybu debugowania, a to wypluje błąd SQL z w końcu pełne cholerne zapytanie. W przeciwnym razie, miejmy nadzieję, że błąd pojawi się w pliku dziennika, jeśli został uruchomiony z serwera www.

 -1
Author: Spencer Williams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-14 22:17:26