Подтвердить что ты не робот

Как отобразить подготовленный оператор MySQLi?

Я сейчас играю с 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

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

4b9b3361

Ответ 1

Я не думаю, что вы можете - по крайней мере, не так, как вы надеялись. Вам нужно либо самостоятельно построить строку запроса, либо выполнить ее (т.е. Без использования оператора), либо искать или создавать оболочку, поддерживающую эту функциональность. Тот, который я использую, 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')

Ответ 2

Я боролся с этим в прошлом. Поэтому, чтобы обойти это, я написал небольшую функцию для создания 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 Подготовить контрольную отметку о выпуске

Ответ 3

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

Ответ 4

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


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

https://github.com/noahheck/E_mysqli

Это набор классов, которые расширяют классы native mysqli и mysqli_stmt, чтобы вы могли просмотреть пример запроса, который будет выполняться на сервере db, путем интерполяции связанных параметров в подготовленный запрос, а затем предоставить вам доступ к результирующей строке запроса как новое свойство объекта 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 = '[email protected]' WHERE entryId = 5569

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

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

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

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

Ответ 5

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

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

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

sql> SET GLOBAL general_log = 'OFF';