tags:

views:

414

answers:

3

I've seen a couple of questions over the last few days that have used mysqli but where the answers appear to have not recognised the difference between $stmt->execute() and $db->query().

As I understand it, there are two differing models for accessing results in mysqli.

This one uses raw SQL and requires the programmer to escape the input to prevent SQL injection attacks, but allows the programmer to retrieve an associative array (or a plain array) containing column => value mappings:

$result_set = $db->query("SAFE SQL QUERY HERE");
while ($row = $result_set->fetch_assoc()) {
     # do something with $row['fieldname'];
}

Alternatively, you can do this, which allows nice binding of parameters and results, but cannot (AFAIK) give you any sort of simple array result:

$stmt = $db-prepare("SQL QUERY WITH ? PLACEHOLDERS");
$stmt->bind_param("s", $input_variable);
$stmt->execute();
$stmt->bind_results($output_col1, $output_col2);
while ($stmt->fetch()) {
     # do something with $output_col1 and $output_col2
}

My question is - is there any way with mysqli to get the simple array output shown in the first pattern, but whilst still using safely bound input parameters as per the second pattern?

I can't find anyway to do this (other than using PDO instead!).

A: 

I would say no. Thought I haven't worked with mysqli or prepared statements a ton, I believe that each step in your second example is discrete and necessary. The only consolation I can give you is that your first example glossed over some SQL escaping that you can safely and truly ignore in your second example.

Jeremy DeGroot
+1  A: 

Alnitak,

AFAIK, you cannot bind an entire array to the fetched results automatically. Unfortunately. However, if you're looking for array behavior out of it (presumably so it's easier to pass the results around), you could try this:

<?php
 $dbh = new mysqli( ... );
 $arr = array();
 if( $stmt = $dbh->prepare( 'SELECT id, email FROM email_list' );
 {
  $stmt->execute();
  $stmt->bind_result( $arr['id'], $arr['email'] );

  while( $stmt->fetch() )
   DoSomething( $arr );
 }
?>

This will give you the behavior you requested, above. It will not, however, dynamically bind array fields to associative indeces in the array -- that is, you must specify that id be bound to $arr['id'], etc.

If dynamic binding to the associative indeces is really required by your scenario, you could always write a simple class that would first parse the query for the selected fields, then setup the assoc array indeces, then perform the query.

Travis Leleu
interesting, but doesn't (AIUI) allow $results[] = $arr, which is a common pattern to get a two-dimensional array of results, since it's using the same $arr each time around the loop. I think you'd have to take a deep copy of $arr before appending it to $results[]
Alnitak
Easy enough to test out, and you're correct! If you want to create a multidimensional array, you will need to perform a deep copy of the bound array. In the while loop, you can do something like $multi[]['id'] = $arr['id']; (for each assoc. index in $arr). This will give you what you need.
Travis Leleu
+1  A: 

There are multiple implementations of a function to do this sort of thing in the comments on this page of the php manual: mysqli_stmt::fetch

Chad Birch