Mysqli get_result alternative

I've just changed all my sql queries to prepared statements using mysqli. To speed this process up I created a function (called performQuery) which replaces mysql_query. It takes the query, the bindings (like "sdss") and the variables to pass in, this then does all the perpared statement stuff. This meant changing all my old code was easy. My function returns a mysqli_result object using mysqli get_result().

This meant I could change my old code from:

$query = "SELECT x FROM y WHERE z = $var";
$result = mysql_query($query);
while ($row = mysql_fetch_assoc($result)){
    echo $row['x'];
}

to

$query = "SELECT x FROM y WHERE z = ?";
$result = performQuery($query,"s",$var);
while ($row = mysql_fetch_assoc($result)){
    echo $row['x'];
}

This works fine on localhost, but my web hosting server does not have mysqlnd available, therefore get_result() does not work. Installing mysqlnd is not an option.

What is the best way to go from here? Can I create a function which replaces get_result(), and how?


Here is a neater solution based on the same principle as lx answer:

function get_result( $Statement ) {
    $RESULT = array();
    $Statement->store_result();
    for ( $i = 0; $i < $Statement->num_rows; $i++ ) {
        $Metadata = $Statement->result_metadata();
        $PARAMS = array();
        while ( $Field = $Metadata->fetch_field() ) {
            $PARAMS[] = &$RESULT[ $i ][ $Field->name ];
        }
        call_user_func_array( array( $Statement, 'bind_result' ), $PARAMS );
        $Statement->fetch();
    }
    return $RESULT;
}

With mysqlnd you would normally do:

$Statement = $Database->prepare( 'SELECT x FROM y WHERE z = ?' );
$Statement->bind_param( 's', $z );
$Statement->execute();
$Result = $Statement->get_result();
while ( $DATA = $Result->fetch_array() ) {
    // Do stuff with the data
}

And without mysqlnd:

$Statement = $Database->prepare( 'SELECT x FROM y WHERE z = ?' );
$Statement->bind_param( 's', $z );
$Statement->execute();
$RESULT = get_result( $Statement );
while ( $DATA = array_shift( $RESULT ) ) {
    // Do stuff with the data
}

So the usage and syntax are almost identical. The main difference is that the replacement function returns a result array, rather than a result object.


I encountered the same problem and solved it using the code provided in the answer of What's wrong with mysqli::get_result?

My function looks like this now (error handling stripped out for clarity):

  function db_bind_array($stmt, &$row)
  {
    $md = $stmt->result_metadata();
    $params = array();
    while($field = $md->fetch_field()) {
        $params[] = &$row[$field->name];
    }
    return call_user_func_array(array($stmt, 'bind_result'), $params);
  }

  function db_query($db, $query, $types, $params)
  {
    $ret = FALSE;
    $stmt = $db->prepare($query);
    call_user_func_array(array($stmt,'bind_param'),
                         array_merge(array($types), $params));
    $stmt->execute();

    $result = array();
    if (db_bind_array($stmt, $result) !== FALSE) {
      $ret = array($stmt, $result);
    }

    $stmt->close();
    return $ret;
  }

Usage like this:

  $userId = $_GET['uid'];
  $sql = 'SELECT name, mail FROM users WHERE user_id = ?';
  if (($qryRes = db_query($db, $sql, 'd', array(&$userId))) !== FALSE) {
    $stmt = $qryRes[0];
    $row  = $qryRes[1];

    while ($stmt->fetch()) {
      echo '<p>Name: '.$row['name'].'<br>'
             .'Mail: '.$row['mail'].'</p>';
    }
    $stmt->close();
  }