Я понимаю, что прошло много времени с тех пор, как по этому вопросу были какие-то новые действия. Но, как прокомментировали другие авторы, 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 - количество полей в операторе select) в звонилке 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()
. Комментарии приветствуются.