Как повторить MySQLi подготовленный оператор? - PullRequest
45 голосов
/ 08 июня 2009

Я сейчас играю с MySQLi, пытаясь понять, как все это работает. В моих текущих проектах мне всегда нравится выводить строку запроса во время кодирования, просто чтобы убедиться, что все правильно, и быстро отладить мой код. Но ... как я могу сделать это с подготовленным оператором MySQLi?

Пример:

$id = 1;
$baz = 'something';

if ($stmt = $mysqli->prepare("SELECT foo FROM bar WHERE id=? AND baz=?")) {
  $stmt->bind_param('is',$id,$baz);
  // how to preview this prepared query before acutally executing it?
  // $stmt->execute();
}

Я просматривал этот список (http://www.php.net/mysqli), но без удачи.


РЕДАКТИРОВАТЬ

Ну, если это невозможно изнутри MySQLi, возможно, я буду придерживаться чего-то вроде этого:

function preparedQuery($sql,$params) {
  for ($i=0; $i<count($params); $i++) {
    $sql = preg_replace('/\?/',$params[$i],$sql,1);
  }
  return $sql;
}

$id = 1;
$baz = 'something';

$sql = "SELECT foo FROM bar WHERE id=? AND baz=?";

echo preparedQuery($sql,array($id,$baz));

// outputs: SELECT foo FROM bar WHERE id=1 AND baz=something

Очевидно, что он далек от совершенства, поскольку он все еще довольно избыточен & mdash; что-то, что я хотел предотвратить & mdash; и это также не дает мне представления о том, что делается с данными MySQLi. Но я думаю, что таким образом я смогу быстро увидеть, все ли данные присутствуют и находятся в нужном месте, и это сэкономит мне некоторое время по сравнению с подгонкой переменных вручную к запросу & mdash; это может быть боль со многими переменными.

Ответы [ 5 ]

10 голосов
/ 08 июня 2009

Я не думаю, что вы можете - по крайней мере, не так, как вы надеялись. Вам нужно будет либо создать строку запроса самостоятельно и выполнить ее (то есть без использования оператора), либо искать или создавать оболочку, поддерживающую эту функцию. Я использую Zend_Db , и вот как я бы это сделал:

$id = 5;
$baz = 'shazam';
$select = $db->select()->from('bar','foo')
                       ->where('id = ?', $id)
                       ->where('baz = ?', $baz); // Zend_Db_Select will properly quote stuff for you
print_r($select->__toString()); // prints SELECT `bar`.`foo` FROM `bar` WHERE (id = 5) AND (baz = 'shazam')
6 голосов
/ 26 июля 2012

Я боролся с этим в прошлом. Чтобы обойти это, я написал небольшую функцию для построения SQL для меня на основе SQL, флагов и переменных.

//////////// Test Data //////////////
$_GET['filmID'] = 232;
$_GET['filmName'] = "Titanic";
$_GET['filmPrice'] = 10.99;

//////////// Helper Function //////////////
function debug_bind_param(){
    $numargs = func_num_args();
    $numVars = $numargs - 2;
    $arg2 = func_get_arg(1);
    $flagsAr = str_split($arg2);
    $showAr = array();
    for($i=0;$i<$numargs;$i++){
        switch($flagsAr[$i]){
        case 's' :  $showAr[] = "'".func_get_arg($i+2)."'";
        break;
        case 'i' :  $showAr[] = func_get_arg($i+2);
        break;  
        case 'd' :  $showAr[] = func_get_arg($i+2);
        break;  
        case 'b' :  $showAr[] = "'".func_get_arg($i+2)."'";
        break;  
        }
    }
    $query = func_get_arg(0);
    $querysAr = str_split($query);
    $lengthQuery = count($querysAr);
    $j = 0;
    $display = "";
    for($i=0;$i<$lengthQuery;$i++){
        if($querysAr[$i] === '?'){
            $display .= $showAr[$j];
            $j++;   
        }else{
            $display .= $querysAr[$i];
        }
    }
    if($j != $numVars){
        $display = "Mismatch on Variables to Placeholders (?)"; 
    }
    return $display;
}

//////////// Test and echo return //////////////

echo debug_bind_param("SELECT filmName FROM movies WHERE filmID = ? AND filmName = ? AND price = ?", "isd", $_GET['filmID'], $_GET['filmName'], $_GET['filmPrice']);

Я также разработал небольшой онлайн-инструмент, чтобы помочь.

Mysqli Prepare Statement Checker

4 голосов
/ 08 июня 2009

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

2 голосов
/ 26 июля 2014

Я недавно обновил этот проект, включив в него интеграцию с композитором, модульное тестирование и улучшенную обработку принимаемых аргументов по ссылке (для этого требуется обновление до версии 5.6).


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

https://github.com/noahheck/E_mysqli

Это набор классов, которые расширяют собственные классы mysqli и mysqli_stmt, чтобы вы могли просматривать пример запроса, который будет выполнен на сервере БД, путем интерполяции связанных параметров в подготовленный запрос и предоставления вам доступ к результирующей строке запроса в качестве нового свойства объекта stmt:

$mysqli  = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName);

$query = "UPDATE registration SET name = ?, email = ? WHERE entryId = ?";

$stmt = $mysqli->prepare($query);

$stmt->bindParam("ssi", $_POST['name'], $_POST['email'], $_POST['entryId']);

$stmt->execute();

echo $stmt->fullQuery;

Результатом будет:

UPDATE registration SET name = 'Sue O\'reilly', email = 'sue.o@example.com' WHERE entryId = 5569

Обратите внимание, что значения в fullQuery экранируются надлежащим образом с учетом набора символов на сервере БД, что должно сделать эту функцию подходящей, например, для файлы журналов, резервные копии и т. д.

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

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

Отказ от ответственности - Как я уже сказал, я сделал это расширение.

0 голосов
/ 20 августа 2018

Вы можете включить запросы журнала на сервере MySQL. Просто выполните команду:

sql> SHOW VARIABLES LIKE "general_log%";
sql> SET GLOBAL general_log = 'ON';

И смотреть запросы в лог-файл. После тестирования выключите логин:

sql> SET GLOBAL general_log = 'OFF';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...