Я понимаю, что уже давно не было никаких новых действий по этому вопросу. Но, как прокомментировали другие get_result()
авторы, теперь это доступно только в PHP после установки собственного драйвера MySQL (mysqlnd), и в некоторых случаях установка mysqlnd может быть невозможной или нежелательной. Итак, я подумал, что было бы полезно опубликовать этот ответ с информацией о том, как получить предлагаемую функциональность get_result()
- без использования get_result()
.
get_result()
Часто используется в сочетании с, fetch_array()
чтобы перебирать набор результатов и сохранять значения из каждой строки набора результатов в числовом индексе или ассоциативном массиве. Например, приведенный ниже код использует get_result () с fetch_array () для циклического просмотра набора результатов, сохраняя значения из каждой строки в массиве $ data [] с числовой индексацией:
$c=1000;
$sql="select account_id, username from accounts where account_id<?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('i', $c);
$stmt->execute();
$result = $stmt->get_result();
while($data = $result->fetch_array(MYSQLI_NUM)) {
print $data[0] . ', ' . $data[1] . "<BR>\n";
}
Однако, если get_result()
он недоступен (поскольку mysqlnd не установлен), это приводит к проблеме того, как сохранить значения из каждой строки набора результатов в массиве без использования get_result()
. Или как перенести устаревший код, который используется get_result()
для работы без него (например, используяbind_result()
вместо него), при этом как можно меньше влияя на остальную часть кода.
Оказывается, сохранение значений из каждой строки в массиве с числовым индексом не так просто использовать bind_result()
. bind_result()
ожидает список скалярных переменных (не массив). Итак, требуется некоторое усилие, чтобы заставить его сохранять значения из каждой строки набора результатов в массиве.
Конечно, код можно легко изменить следующим образом:
$c=1000;
$sql="select account_id, username from accounts where account_id<?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('i', $c);
$stmt->execute();
$stmt->bind_result($data[0], $data[1]);
while ($stmt->fetch()) {
print $data[0] . ', ' . $data[1] . "<BR>\n";
}
Но это требует, чтобы мы явно перечисляли $ data [0], $ data [1] и т. Д. По отдельности в вызове bind_result()
, что не идеально. Нам нужно решение, которое не требует от нас явного перечисления $ data [0], $ data [1], ... $ data [N-1] (где N - количество полей в операторе выбора) в звонке bind_results()
. Если мы переносим устаревшее приложение с большим количеством запросов, и каждый запрос может содержать разное количество полей в select
предложении, миграция будет очень трудоемкой и подвержена ошибкам, если мы будем использовать решение, подобное приведенному выше. .
В идеале нам нужен фрагмент кода «вставной замены» - чтобы заменить только строку, содержащую get_result()
функцию и цикл while (), на следующей строке. Код замены должен иметь ту же функцию, что и код, который он заменяет, не затрагивая ни одну из строк до или любую из строк после, включая строки внутри цикла while (). В идеале мы хотим, чтобы код замены был как можно более компактным, и мы не хотим, чтобы код замены зависел от количества полей в select
предложении запроса.
Поискав в Интернете, я нашел ряд решений, которые используются bind_param()
с call_user_func_array()
(например, динамически связывают параметры mysqli_stmt, а затем связывают результат (PHP) ), но большинство решений, которые я нашел, в конечном итоге приводят к тому, что результаты сохраняются в ассоциативном массиве, а не массив с числовой индексацией, и многие из этих решений были не такими компактными, как хотелось бы, и / или не подходили в качестве «заменяемых элементов». Однако из примеров, которые я нашел, я смог сколотить это решение, которое отвечает всем требованиям:
$c=1000;
$sql="select account_id, username from accounts where account_id<?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('i', $c);
$stmt->execute();
$data=array();
for ($i=0;$i<$mysqli->field_count;$i++) {
$var = $i;
$$var = null;
$data[$var] = &$$var;
}
call_user_func_array(array($stmt,'bind_result'), $data);
while ($stmt->fetch()) {
print $data[0] . ', ' . $data[1] . "<BR>\n";
}
Конечно, цикл for () можно свернуть в одну строку, чтобы сделать его более компактным.
Я надеюсь, что это поможет любому, кто ищет решение, использующее bind_result()
для хранения значений из каждой строки в массиве с числовой индексацией и / или ищущий способ переноса устаревшего кода с использованием get_result()
. Комментарии приветствуются.
$stmt = $conn->mysqli->stmt_init();
?