Here\'s my code:
include \'conn.php\';
$conn = new Connection();
$query = \'SELECT EmailVerified, Blocked FROM users WHERE Email = ? AND SLA = ? AND `Passwo
I have written two simple functions that give the same functionality as $stmt->get_result();
, but they don't require the mysqlnd driver.
You simply replace
$result = $stmt->get_result();
with $fields = bindAll($stmt);
and
$row= $stmt->get_result();
with $row = fetchRowAssoc($stmt, $fields);
.
(To get the numbers of returned rows you can use $stmt->num_rows
.)
You just have to place these two functions I have written somewhere in your PHP Script. (for example right at the bottom)
function bindAll($stmt) {
$meta = $stmt->result_metadata();
$fields = array();
$fieldRefs = array();
while ($field = $meta->fetch_field())
{
$fields[$field->name] = "";
$fieldRefs[] = &$fields[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $fieldRefs);
$stmt->store_result();
//var_dump($fields);
return $fields;
}
function fetchRowAssoc($stmt, &$fields) {
if ($stmt->fetch()) {
return $fields;
}
return false;
}
How it works:
My code uses the $stmt->result_metadata();
function to figure out how many and which fields are returned and then automatically binds the fetched results to pre-created references. Works like a charm!
I realize that it's been a while since there has been any new activity on this question. But, as other posters have commented - get_result()
is now only available in PHP by installing the MySQL native driver (mysqlnd), and in some cases, it may not be possible or desirable to install mysqlnd. So, I thought it would be helpful to post this answer with info on how get the functionality that get_result()
offers - without using get_result()
.
get_result()
is/was often combined with fetch_array()
to loop through a result set and store the values from each row of the result set in a numerically-indexed or associative array. For example, the code below uses get_result() with fetch_array() to loop through a result set, storing the values from each row in the numerically-indexed $data[] array:
$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";
}
However, if get_result()
is not available (because mysqlnd is not installed), then this leads to the problem of how to store the values from each row of a result set in an array, without using get_result()
. Or, how to migrate legacy code that uses get_result()
to run without it (e.g. using bind_result()
instead) - while impacting the rest of the code as little as possible.
It turns out that storing the values from each row in a numerically-indexed array is not so straight-forward using bind_result()
. bind_result()
expects a list of scalar variables (not an array). So, it takes some doing to make it store the values from each row of the result set in an array.
Of course, the code could easily be modified as follows:
$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";
}
But, this requires us to explicitly list $data[0], $data[1], etc. individually in the call to bind_result()
, which is not ideal. We want a solution that doesn't require us to have to explicitly list $data[0], $data[1], ... $data[N-1] (where N is the number of fields in the select statement) in the call to bind_results()
. If we're migrating a legacy application that has a large number of queries, and each query may contain a different number of fields in the select
clause, the migration will be very labor intensive and prone to error if we use a solution like the one above.
Ideally, we want a snippet of 'drop-in replacement' code - to replace just the line containing the get_result()
function and the while() loop on the next line. The replacement code should have the same function as the code that it's replacing, without affecting any of the lines before, or any of the lines after - including the lines inside the while() loop. Ideally we want the replacement code to be as compact as possible, and we don't want to have to taylor the replacement code based on the number of fields in the select
clause of the query.
Searching on the internet, I found a number of solutions that use bind_param()
with call_user_func_array()
(for example, Dynamically bind mysqli_stmt parameters and then bind result (PHP)), but most solutions that I found eventually lead to the results being stored in an associative array, not a numerically-indexed array, and many of these solutions were not as compact as I would like and/or were not suited as 'drop-in replacements'. However, from the examples that I found, I was able to cobble together this solution, which fits the bill:
$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";
}
Of course, the for() loop can be collapsed into one line to make it more compact.
I hope this helps anyone who is looking for a solution using bind_result()
to store the values from each row in a numerically-indexed array and/or looking for a way to migrate legacy code using get_result()
. Comments welcome.
So if the MySQL Native Driver (mysqlnd) driver is not available, and therefore using bind_result and fetch instead of get_result, the code becomes:
include 'conn.php';
$conn = new Connection();
$query = 'SELECT EmailVerified, Blocked FROM users WHERE Email = ? AND SLA = ? AND `Password` = ?';
$stmt = $conn->mysqli->prepare($query);
$stmt->bind_param('sss', $_POST['EmailID'], $_POST['SLA'], $_POST['Password']);
$stmt->execute();
$stmt->bind_result($EmailVerified, $Blocked);
while ($stmt->fetch())
{
/* Use $EmailVerified and $Blocked */
}
$stmt->close();
$conn->mysqli->close();
With PHP version 7.2 I just used nd_mysqli instead of mysqli and it worked as expected.
Steps to enable it into godaddy hosting server-