Как отлаживать запросы к базе данных PDO? - PullRequest
130 голосов
/ 09 марта 2010

Прежде чем перейти на PDO, я создал SQL-запросы в PHP путем объединения строк. Если я получил ошибку синтаксиса базы данных, я мог бы просто отобразить окончательную строку запроса SQL, попробовать ее самостоятельно в базе данных и настроить ее, пока я не исправлю ошибку, а затем вставить ее обратно в код.

Подготовленные операторы PDO быстрее, лучше и безопаснее, но меня беспокоит одна вещь: я никогда не увижу окончательный запрос при его отправке в базу данных. Когда я получаю ошибки о синтаксисе в моем журнале Apache или в моем пользовательском файле журнала (я регистрирую ошибки внутри блока catch), я не вижу запрос, который их вызвал.

Есть ли способ перехватить полный SQL-запрос, отправленный PDO в базу данных, и записать его в файл?

Ответы [ 18 ]

96 голосов
/ 09 марта 2010

Вы говорите это:

Я никогда не вижу окончательный запрос, так как отправлено в базу данных

Ну, на самом деле, при использовании подготовленных операторов, не существует такой вещи, как " конечный запрос " :

  • Сначала заявление отправляется в БД и там готовится
    • База данных анализирует запрос и создает его внутреннее представление
  • И, когда вы связываете переменные и выполняете оператор, в базу данных отправляются только переменные
    • И база данных «внедряет» значения во внутреннее представление оператора


Итак, чтобы ответить на ваш вопрос:

Есть ли способ захвата полного SQL-запрос, отправленный PDO в базу данных и записать его в файл?

Нет: поскольку нигде нет " завершенного запроса SQL ", его невозможно перехватить.


Лучшее, что вы можете сделать для целей отладки, - это «восстановить» «настоящий» SQL-запрос, введя значения в строку SQL оператора.

Что я обычно делаю в таких ситуациях:

  • эхо-код SQL, соответствующий инструкции, с заполнителями
  • и используйте var_dump (или эквивалент) сразу после, чтобы отобразить значения параметров
  • Обычно этого достаточно, чтобы увидеть возможную ошибку, даже если у вас нет «реального» запроса, который вы можете выполнить.

Это не очень хорошо, когда дело доходит до отладки, но это цена готовых утверждений и преимуществ, которые они приносят.

83 голосов
/ 10 марта 2010

Просмотр в журнале базы данных

Хотя Pascal MARTIN правильно, что PDO не отправляет полный запрос к базе данных сразу, предложение ryeguy использовать функцию ведения журнала БД фактически позволило мне увидеть полный запрос как собранный и выполненный базой данных.

Вот как: (Эти инструкции для MySQL на компьютере с Windows - ваш пробег может отличаться)

  • В my.ini в разделе [mysqld] добавьте команду log, например log="C:\Program Files\MySQL\MySQL Server 5.1\data\mysql.log"
  • Перезагрузите MySQL.
  • Он начнет регистрировать каждый запрос в этом файле.

Этот файл будет быстро расти, поэтому обязательно удалите его и отключите ведение журнала, когда закончите тестирование.

14 голосов
/ 03 июля 2012

Конечно, вы можете отлаживать, используя этот режим {{ PDO::ATTR_ERRMODE }} Просто добавьте новую строку перед запросом, и вы увидите строки отладки.

$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$db->query('SELECT *******');  
14 голосов
/ 09 мая 2011

Вероятно, вы хотите использовать debugDumParams () Он не создает подготовленный оператор для вас, но он покажет ваши параметры.

12 голосов
/ 10 апреля 2012

Старый пост, но, возможно, кто-то найдет это полезным;

function pdo_sql_debug($sql,$placeholders){
    foreach($placeholders as $k => $v){
        $sql = preg_replace('/:'.$k.'/',"'".$v."'",$sql);
    }
    return $sql;
}
9 голосов
/ 11 октября 2013

Вот функция, чтобы увидеть, какой будет эффективный SQL, дополненный комментарием "Mark" на php.net :

function sql_debug($sql_string, array $params = null) {
    if (!empty($params)) {
        $indexed = $params == array_values($params);
        foreach($params as $k=>$v) {
            if (is_object($v)) {
                if ($v instanceof \DateTime) $v = $v->format('Y-m-d H:i:s');
                else continue;
            }
            elseif (is_string($v)) $v="'$v'";
            elseif ($v === null) $v='NULL';
            elseif (is_array($v)) $v = implode(',', $v);

            if ($indexed) {
                $sql_string = preg_replace('/\?/', $v, $sql_string, 1);
            }
            else {
                if ($k[0] != ':') $k = ':'.$k; //add leading colon if it was left out
                $sql_string = str_replace($k,$v,$sql_string);
            }
        }
    }
    return $sql_string;
}
8 голосов
/ 09 марта 2010

Нет. Запросы PDO не подготавливаются на стороне клиента. PDO просто отправляет запрос SQL и параметры на сервер базы данных. база данных - это то, что заменяет (?). У вас есть два варианта:

  • Используйте функцию журналирования вашей БД (но даже тогда она обычно отображается в виде двух отдельных операторов (т. Е. «Не окончательно») по крайней мере с Postgres)
  • Вывести запрос SQL и параметры и собрать его воедино сам
5 голосов
/ 26 марта 2013

почти ничего не было сказано об отображении ошибок, кроме проверки журналов ошибок, но есть довольно полезная функциональность:

<?php
/* Provoke an error -- bogus SQL syntax */
$stmt = $dbh->prepare('bogus sql');
if (!$stmt) {
    echo "\PDO::errorInfo():\n";
    print_r($dbh->errorInfo());
}
?>

( ссылка на источник )

ясно, что этот код может быть изменен для использования в качестве сообщения об исключении или любой другой вид обработки ошибок

3 голосов
/ 26 декабря 2012

например, у вас есть этот оператор pdo:

$query="insert into tblTest (field1, field2, field3)
values (:val1, :val2, :val3)";
$res=$db->prepare($query);
$res->execute(array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
));

теперь вы можете получить выполненный запрос, определив массив следующим образом:

$assoc=array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
);
$exQuery=str_replace(array_keys($assoc), array_values($assoc), $query);
echo $exQuery;
2 голосов
/ 18 ноября 2016

Чтобы зарегистрировать MySQL в WAMP , вам необходимо отредактировать my.ini (например, в wamp \ bin \ mysql \ mysql5.6.17 \ my.ini)

и добавить к [mysqld]:

general_log = 1
general_log_file="c:\\tmp\\mysql.log"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...