Cantidad variable de columnas devueltas en la statement preparada de mysqli

Tengo una situación en la que se genera una consulta dinámica que podría seleccionar de 1 a más de 300 columnas diferentes en varias tablas. Actualmente funciona bien solo haciendo una consulta, sin embargo, el problema con el que me estoy encontrando al usar una statement preparada es que no sé cómo manejar el hecho de que no sé cuántas columnas voy a pedir cada vez y por lo tanto, no sé cómo procesar los resultados. La razón por la que creo que una sentencia de vinculación ayudará es porque una vez que esta consulta se ejecuta una vez, lo más probable es que (aunque no siempre) se ejecute de nuevo con exactamente los mismos parámetros.

Actualmente tengo algo como esto:

$rows = array(); $this->statement = $this->db->prepare($query); $this->statement->bind_param('i',$id); $this->statement->execute(); $this->statement->bind_result($result); while($this->statement->fetch()) { $rows[] = $result; } 

Sé que esto no funciona como yo quiero, mi pregunta es cómo puedo recuperar los datos de la consulta. ¿Es posible volver a colocar las columnas en una matriz asociativa por nombre de columna, como una consulta estándar de mysqli?

Prever no usar eval , esta es mi solución (similar a ashurexm):

 $md = $stmt -> result_metadata(); $fields = $md -> fetch_fields(); $result = new stdClass(); // Actual result object $params = array(); // Array of fields passed to the bind_result method foreach($fields as $field) { $result -> {$field -> name} = null; $params[] = &$result -> {$field -> name}; } call_user_func_array(array($stmt, 'bind_result'), $params); 

Utilizando la sugerencia de mysqli_statement->result_metadata() de mysqli_statement->result_metadata() pude mysqli_statement->result_metadata() juntos el siguiente código que logra lo que estoy buscando, aunque el rendimiento no es más rápido que usar una consulta estándar. Obtengo la statement->result_metadata() para construir una matriz asociativa para llamar bind_result on. Construyo una statement bind_result como una cadena y la eval . Sé que esto no es particularmente seguro, pero es mi primer paso.

 public function executePreparedStatement() { if($this->statement->execute()) { $this->record = array(); $md = $this->statement->result_metadata(); $fields = $md->fetch_fields(); $bindResult = '$this->statement->bind_result('; foreach($fields as $field) { $bindResult .= "\$this->record['" . $field->name . "'],"; } $bindResult = substr($bindResult,0,strlen($bindResult) - 1) . ');'; eval($bindResult); return true; } else { $this->error = $this->db->error; return false; } } ... $this->prepareStatement($query); $this->bindParameter('i',$runId); if($this->executePreparedStatement()) { $report = new Report(); while($this->statement->fetch()) { $row = $this->record; $line = array(); foreach($row as $key => &$value) { array_push($line,$value); } $report->addLine($line); } return $report } 

Esta es la razón por la cual mysqli nunca debe usarse con declaraciones preparadas.
Por lo tanto, debe usar PDO en su lugar, lo que hará que executePreparedStatement () se convierta en tres líneas:

 function executePreparedStatement($sql,$params) { $stm = $this->db->prepare($sql); $stm->execute($params); return $stm->fetchAll(); } 

usado así

 $sql = "SELECT * from news WHERE category=?"; $data = $this->executePreparedStatement($sql,$_GET['category']);