Zdaję sobie sprawę, że minęło trochę czasu, odkąd pojawiły się nowe działania w tej kwestii. Ale, jak komentowali inni plakaty - get_result()
jest teraz dostępny tylko w PHP po zainstalowaniu natywnego sterownika MySQL (mysqlnd), aw niektórych przypadkach może nie być możliwe lub pożądane zainstalowanie mysqlnd. Pomyślałem więc, że pomocne byłoby opublikowanie tej odpowiedzi z informacjami o tym, jak uzyskać oferowaną funkcjonalność get_result()
- bez użycia get_result()
.
get_result()
jest / był często łączony z, fetch_array()
aby zapętlić zestaw wyników i przechowywać wartości z każdego wiersza zestawu wyników w tablicy indeksowanej numerycznie lub asocjacyjnej. Na przykład poniższy kod wykorzystuje metodę get_result () z funkcją fetch_array () do przechodzenia przez zestaw wyników, przechowując wartości z każdego wiersza w tablicy $ data [] indeksowanej numerycznie:
$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";
}
Jeśli jednak get_result()
nie jest dostępny (ponieważ mysqlnd nie jest zainstalowany), prowadzi to do problemu z przechowywaniem wartości z każdego wiersza zestawu wyników w tablicy bez użycia get_result()
. Albo jak przeprowadzić migrację starszego kodu, get_result()
który działa bez niego (np. Używając bind_result()
zamiast tego) - przy jak najmniejszym wpływie na resztę kodu.
Okazuje się, że przechowywanie wartości z każdego wiersza w tablicy indeksowanej numerycznie nie jest tak proste w użyciu bind_result()
. bind_result()
oczekuje listy zmiennych skalarnych (nie tablicy). Tak więc wymaga trochę pracy, aby przechowywać wartości z każdego wiersza zestawu wyników w tablicy.
Oczywiście kod można łatwo zmodyfikować w następujący sposób:
$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";
}
Ale to wymaga od nas, abyśmy w wywołaniu funkcji wyraźnie wymieniali $ data [0], $ data [1] itd. bind_result()
, Co nie jest idealne. Chcemy rozwiązania, które nie wymaga od nas jawnej listy $ data [0], $ data [1], ... $ data [N-1] (gdzie N to liczba pól w instrukcji select) w wezwaniu do bind_results()
. Jeśli przeprowadzamy migrację starszej aplikacji, która ma dużą liczbę zapytań, a każde zapytanie może zawierać inną liczbę pól w select
klauzuli, migracja będzie bardzo pracochłonna i podatna na błędy, jeśli użyjemy rozwiązania takiego jak powyższe .
Idealnie byłoby, gdybyśmy potrzebowali fragmentu kodu „zastępującego wstawianie” - aby zastąpić tylko wiersz zawierający get_result()
funkcję i pętlę while () w następnym wierszu. Kod zastępczy powinien mieć taką samą funkcję jak kod, który zastępuje, bez wpływu na żadną z wierszy przed ani na wiersze po - w tym wiersze wewnątrz pętli while (). W idealnym przypadku chcemy, aby kod zastępczy był możliwie jak najbardziej zwarty i nie chcemy modyfikować kodu zastępczego na podstawie liczby pól w select
klauzuli zapytania.
Szukając w Internecie, znalazłem szereg rozwiązań, które używają bind_param()
z call_user_func_array()
(na przykład Dynamiczne wiązanie parametrów mysqli_stmt, a następnie wiązanie wyniku (PHP) ), ale większość rozwiązań, które znalazłem, ostatecznie prowadzi do przechowywania wyników w tablicy asocjacyjnej, a nie tablica indeksowana numerycznie, a wiele z tych rozwiązań nie było tak zwartych, jak bym chciał i / lub nie nadawało się jako „zamienniki typu drop-in”. Jednak z przykładów, które znalazłem, udało mi się zebrać razem to rozwiązanie, które pasuje do rachunku:
$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";
}
Oczywiście pętlę for () można zwinąć w jedną linię, aby była bardziej zwarta.
Mam nadzieję, że pomoże to każdemu, kto szuka rozwiązania używającego bind_result()
do przechowywania wartości z każdego wiersza w tablicy indeksowanej numerycznie i / lub szukającego sposobu na migrację starszego kodu przy użyciu get_result()
. Komentarze mile widziane.
$stmt = $conn->mysqli->stmt_init();
?