Параметры привязки MySQLI с использованием массива пользовательских функций вызова
пожалуйста, см. ниже мой код. Я пытаюсь привязать массив показателей на мое заявление. Я искал в интернете и вижу, что мне нужно использовать call_user_func_array, но не могу заставить его работать. Ошибка, которую я получаю,: "Первый аргумент, как ожидается, будет допустимым обратным вызовом, "массив" был дан" Возможно, я ошибаюсь, но я предполагаю, что первый аргумент может быть массивом, и, возможно, это сообщение об ошибке вводит в заблуждение. Я думаю, проблема в том, что мой массив в некотором роде виноват. Может кто-нибудь видеть, что я делаю не так? Спасибо.
$type = array("s", "s");
$param = array("string1","anotherstring");
$stmt = $SQLConnection->prepare("INSERT INTO mytable (comp, addl) VALUES (?,?)");
$params = array_merge($type, $param);
call_user_func_array(array(&$stmt, 'bind_param'), $params);
$SQLConnection->execute();
7 ответов
Я не знаю, почему вы обязательно использовать call_user_func_array
, но это уже другая история.
call_user_func_array(array($stmt, 'bind_param'), $params);
это должно быть так:
//connect
$mysqli = new mysqli($host, $user, $password, $db_name);
//prepare
$stmt = $mysqli->prepare("SELECT * FROM the_table WHERE field1= ? AND Field2= ?");
//Binding parameters. Types: s = string, i = integer, d = double, b = blob
$params= array("ss","string_1","string_2");
//now we need to add references
$tmp = array();
foreach($params as $key => $value) $tmp[$key] = &$params[$key];
// now us the new array
call_user_func_array(array($stmt, 'bind_param'), $tmp);
$stmt->execute();
/* Fetch result to array */
$res = $stmt->get_result();
while($row = $res->fetch_array(MYSQLI_ASSOC)) {
$a_data[]=$row;
}
print_r($a_data);
$stmt->close();
не смог ответить на этот вопрос, потому что он был помечен как dupe: здесь. Но я думаю, что мое окончательное решение, которое использует ответы в этом вопросе, работает в моем случае использования, может быть полезно для кого-то.
мои цели состояли в том, чтобы взять опубликованный набор идентификаторов и использовать их в NOT IN
оператор MYSQL. Предполагая, что массив из 5 ID размещен.
подсчитайте количество опубликованных идентификаторов для создания
?
заполнителиNOT IN
заявление. Используя$params_count = substr(str_repeat(',?', count($array_of_ids)), 1);
дает результат:(?,?,?,?,?)
для использования в инструкции SQL.-
сделать функцию, которая принимает ID и введите
i
илиs
etc. Для меня они все былиi
таким образом, моя функция проще. возвращает массив, который выглядит следующим образом$params= array("iiiii",1,2,3,4,5)
где первым значением является множествоi
и последующие значения являются идентификаторами в зависимости от общего идентификатора, переданного в функция.function build_bind_params($values, $bind_type) { $s = substr(str_repeat($bind_type, count($values)), 0); $bind_array = array(); $bind_array[] = $s; foreach($values as $value) { $bind_array[] = $value; } return $bind_array; }
$params = build_bind_params($array_of_ids, "i");
затем использовать
foreach ($params as $key => $value) $tmp[$key] = &$params[$key];
чтобы получить вновь созданный$params
правильно отформатирован для привязки.затем использовать
call_user_func_array(array($stmt , 'bind_param') , $tmp);
для правильной привязки массива.выполнить
$stmt
большинство из вышеперечисленных не являются решениями без интеграции типов вместе со значениями перед их добавлением в call_user_func_array (). Это решение сработало для меня:
/* create a database connection */
$db = new mysqli($host, $user, $password, $db_name);
/* setup the sql, values, and types */
$sql="SELECT * FROM languages
WHERE language_code = ?
AND charset = ?
ORDER BY native_name";
$values = array($langCode, $charset);
$types = "ss";
/* pass those variables to the execute() function defined below */
if ($rows = execute($sql, $values, $types))
{
return $rows[0];
}
function execute($sql, $values='', $types='')
{
/* prepare the sql before binding values and types */
$stmt = $db->prepare($sql);
/*combine the values and types into $inputArray */
$inputArray[] = &$types;
$j = count($values);
for($i=0;$i<$j;$i++){
$inputArray[] = &$values[$i];
}
/* add the combined values and types to call_user_func_array() for binding */
call_user_func_array(array($stmt, 'bind_param'), $inputArray);
$result = $stmt->execute();
return $result;
}
вот ссылка на полное описание, на котором основан этот пример: http://big.info/2015/08/php-use-call_user_func_array-for-variable-number-of-parameters-arrays-in-prepared-statements.html
почему вы хотите вызвать call_user_func_array (array ($statement, 'bind_param'), $bind_arguments)? Потому что $bind_arguments является массивом. У вас есть одна функция, которая связывает оператор с его запрашиваемыми параметрами, независимо от того, сколько параметров у вас было бы иначе.
пример хорошего кода...
<?php
# link
$dblink = new mysqli('HOSTNAME','USERNAME','PASSWORD','DATABASENAME');
# example data
$statement = $dblink->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?");
$recordvalues = ['John', 'H.', 'Smith', 25];
$sqlbindstring = "sssi"; # String, String, String, Integer example
# make the references
$bind_arguments = [];
$bind_arguments[] = $sqlbindstring;
foreach ($recordvalues as $recordkey => $recordvalue)
{
$bind_arguments[] = & $recordvalues[$recordkey]; # bind to array ref, not to the temporary $recordvalue
}
# query the db
call_user_func_array(array($statement, 'bind_param'), $bind_arguments); # bind arguments
$statement->execute(); # run statement
$result = $statement->get_result(); # get results
# get the results
if($result) {
while ($row = $result->fetch_assoc()) {
print("\n\nMy row is...");
print_r($row);
}
}
?>
пример плохого кода...
<?php
# Same setup as above..
$statement->prepare("SELECT * from Person WHERE FirstName = ? AND MiddleName = ? AND LastName = ? and Age = ?");
$statement->bind('John', 'H.", 'Smith', 25);
?>
в первом примере: вы можете передать столько или столько же привязки, чтобы выполнить привязку() может вызываться только в одной строке во всем приложении. Это хорошо масштабируется.
во втором примере: вы должны написать один оператор bind () для каждой возможной группы вставок для каждой возможной записи в вашей базе данных. Это плохо масштабируется.
Если вы получаете ошибку, вы должны попробовать это:
call_user_func_array(array($stmt, 'bind_param'), refValues($params));
function refValues($arr){
if (strnatcmp(phpversion(),'5.3') >= 0) {
$refs = array();
foreach($arr as $key => $value)
$refs[$key] = &$arr[$key];
return $refs;
}
return $arr;
}