Я усвідомлюю, що минуло певний час, оскільки з цього питання не було жодної нової діяльності. Але, як прокоментували інші афіші - 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()
. Коментарі вітаються.
$stmt = $conn->mysqli->stmt_init();
?