Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prepared mysqli select statement on longtext field is coming back empty

I've got a database query function that works well -- except that I'm running into what's apparently a known issue with mysqli prepared statements and longtext fields. What happens is that the longtext field always comes up empty even though running the query through phpMyAdmin works fine. According to http://www.workinginboxershorts.com/php-mysqli-returns-empty-variables-from-longtext-column, switching the datatype to text solves the problem. However, in my case I'd really prefer to leave the field as longtext as I can foresee times when that extra space would be valuable.

I'm using parameterized queries, which evidently is the problem. Here's my function:

// Bind results to an array
// $stmt = sql query, $out = array to be returned
function stmt_bind_assoc (&$stmt, &$out) {
  $data = mysqli_stmt_result_metadata($stmt);
  $fields = array();
  $out = array();

  $fields[0] = $stmt;
  $count = 1;

  while($field = mysqli_fetch_field($data)) {
    $fields[$count] = &$out[$field->name];
    $count++;
  }    
call_user_func_array('mysqli_stmt_bind_result', $fields);
}

// DB Query
// $query = SQL query, $params = array of parameters, $rs = whether or not a resultset is expected, $newid = whether or not to retrieve the new ID value;
// $onedimensionkey = key required to convert array into simple one dimensional array
function db_query($query, $params, $rs = true, $newid = false, $onedimensionkey = false) {
  $link = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);
  if (!$link) { 
    print 'Error connecting to MySQL Server. Errorcode: ' . mysqli_connect_error(); 
    exit; 
  }

  // Prepare the query and split the parameters array into bound values
  if ($sql_stmt = mysqli_prepare($link, $query)) {
    if ($params) {
      $types = '';
      $new_params = array();
      $params_ref = array();
      // Split the params array into types string and parameters sub-array
      foreach ($params as $param) {
        $types .= $param['type'];
        $new_params[] = $param['value'];
      }
      // Cycle the new parameters array to make it an array by reference
      foreach ($new_params as $key => $parameter) {
        $params_ref[] = &$new_params[$key];
      }
      call_user_func_array('mysqli_stmt_bind_param', array_merge(array($sql_stmt, $types), $params_ref));
    }
  }
  else {
    print 'Error: ' . mysqli_error($link);
    exit();
  }

  // Execute the query
  mysqli_stmt_execute($sql_stmt);

  // If there are results to retrive, do so
  if ($rs) {
    $results = array();
    $rows = array();
    $row = array();
    stmt_bind_assoc($sql_stmt, $results);
    while (mysqli_stmt_fetch($sql_stmt)) {
      foreach ($results as $key => $value) {
        $row[$key] = $value;
      }
      $rows[] = $row;
    }
    if ($onedimensionkey) {
      $i = 0;
      foreach ($rows as $row) {
        $simplearray[$i] = $row[$onedimensionkey];
        $i++;
      }
      return $simplearray;
    }
    else {
      return $rows;
    }
  }
  // If there are no results but we need the new ID, return it
  elseif ($newid) {
    return mysqli_insert_id($link);
  }

  // Close objects
  mysqli_stmt_close($sql_stmt);
  mysqli_close($link);
}

According to the link that I posted there is a workaround involving the order in which things are done, but either I'm handling my query in a completely different manner than the example or I'm simply not understanding something important.

Thanks to anyone who can help!

EDIT: Thanks to Corina's answer, I've solved this -- for anyone else who runs into the problem, you will simply need to add the following after the mysql_stmt_execute command:

// Execute the query
mysqli_stmt_execute($sql_stmt);

// Store results
mysqli_stmt_store_result($sql_stmt);
like image 370
Sean Cunningham Avatar asked Apr 26 '12 14:04

Sean Cunningham


1 Answers

I managed to solve the same issue by calling mysqli_stmt_store_result before binding the data.

Someone had the same problem and shared the answer on the php.net website:

Apparently, if you have longtext present, you HAVE to call store_result before using bind_result.

http://bugs.php.net/bug.php?id=47928

like image 53
Corina Avatar answered Nov 11 '22 00:11

Corina