Сейчас я играю с 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. Но я предполагаю, что таким образом я могу быстро увидеть, имеются ли все данные и в нужном месте, и это сэкономит мне некоторое время по сравнению с подстановкой переменных вручную в запрос – это может быть болью со многими варами.
Я не думаю, что вы можете – по крайней мере, не так, как вы надеялись. Вам нужно либо самостоятельно построить строку запроса, либо выполнить ее (т. Е. Без использования оператора), либо искать или создавать оболочку, поддерживающую эту функциональность. Я использую 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')
Я боролся с этим в прошлом. Поэтому, чтобы обойти это, я написал небольшую функцию для создания 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 Подготовьте Checker
Просто установите его, чтобы умереть и вывести последний выполненный запрос. Обработка ошибок должна дать вам значимую информацию, которую вы можете использовать для исправления вашего запроса.
Недавно я обновил этот проект, включив интеграцию композитора, модульное тестирование и улучшив обработку принимаемых аргументов по ссылке (для этого требуется обновление до php 5.6).
В ответ на запрос, полученный мной по проекту, который я создал для решения этой же проблемы с использованием PDO
, я создал расширение для mysqli
на github, похоже, что он решает вашу проблему:
https://github.com/noahheck/E_mysqli
Это набор классов, которые расширяют родные классы 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 = 'sue.o@example.com' WHERE entryId = 5569
Обратите внимание, что значения в fullQuery экранируются соответствующим образом с учетом набора символов на сервере db, что должно сделать эту функциональность подходящей, например, для файлов журналов, резервных копий и т. Д.
Для этого есть несколько предостережений, изложенных в ReadMe в проекте github, но, особенно для разработки, обучения и тестирования, это должно обеспечить некоторую полезную функциональность.
Как я изложил в проекте github, у меня нет практического опыта использования расширения mysqli
, и этот проект был создан по просьбе пользователей его дочернего проекта, поэтому любые отзывы, которые могут быть предоставлены разработчикам, используя это в производство было бы весьма признательным.
Отказ от ответственности. Как я уже сказал, я сделал это расширение.