stmt statement prepared mysqli_stmt_fetch mysqli_stmt_bind_result mysqli_stmt method get_result from fetch_assoc bind_result array php mysqli

statement - php mysqli_stmt bind_result array



Llamada al método indefinido mysqli_stmt:: get_result (8)

Aquí está mi alternativa. Está orientado a objetos y se parece más a las cosas de mysql / mysqli.

class MMySqliStmt{ private $stmt; private $row; public function __construct($stmt){ $this->stmt = $stmt; $md = $stmt->result_metadata(); $params = array(); while($field = $md->fetch_field()) { $params[] = &$this->row[$field->name]; } call_user_func_array(array($stmt, ''bind_result''), $params) or die(''Sql Error''); } public function fetch_array(){ if($this->stmt->fetch()){ $result = array(); foreach($this->row as $k => $v){ $result[$k] = $v; } return $result; }else{ return false; } } public function free(){ $this->stmt->close(); } }

Uso:

$stmt = $conn->prepare($str); //...bind_param... and so on if(!$stmt->execute())die(''Mysql Query(Execute) Error : ''.$str); $result = new MMySqliStmt($stmt); while($row = $result->fetch_array()){ array_push($arr, $row); //for example, use $row[''id''] } $result->free(); //for example, use the $arr

Aquí está mi código:

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(); $result = $stmt->get_result();

Aparece el error en la última línea como: Llamada al método indefinido mysqli_stmt :: get_result ()

Aquí está el código para conn.php:

define(''SERVER'', ''localhost''); define(''USER'', ''root''); define(''PASS'', ''xxxx''); define(''DB'', ''xxxx''); class Connection{ /** * @var Resource */ var $mysqli = null; function __construct(){ try{ if(!$this->mysqli){ $this->mysqli = new MySQLi(SERVER, USER, PASS, DB); if(!$this->mysqli) throw new Exception(''Could not create connection using MySQLi'', ''NO_CONNECTION''); } } catch(Exception $ex){ echo "ERROR: ".$e->getMessage(); } } }

Si escribo esta línea:

if(!stmt) echo ''Statement prepared''; else echo ''Statement NOT prepared'';

Imprime ''Declaración NO preparada'' . Si ejecuto la consulta directamente en el IDE reemplazando? marcas con valores, funciona bien. Tenga en cuenta que el objeto $ conn funciona bien en otras consultas en el proyecto.

Cualquier ayuda por favor .......


Entonces, si el controlador de MySQL Native Driver (mysqlnd) no está disponible, y por lo tanto usa bind_result y fetch en lugar de get_result , el código pasa a ser:

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();


He escrito dos funciones simples que dan la misma funcionalidad que $stmt->get_result(); , pero no requieren el controlador mysqlnd.

Simplemente reemplaza

$result = $stmt->get_result(); con $fields = bindAll($stmt);

y

$row= $stmt->get_result(); con $row = fetchRowAssoc($stmt, $fields); .

(Para obtener los números de las filas devueltas puede usar $stmt->num_rows .)

Simplemente tiene que colocar estas dos funciones que he escrito en algún lugar de su secuencia de comandos PHP . (por ejemplo, justo en la parte inferior)

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; }

Cómo funciona :

Mi código usa $stmt->result_metadata(); función para averiguar cuántos y qué campos se devuelven y luego vincula automáticamente los resultados obtenidos a las referencias creadas previamente. ¡Funciona de maravilla!


Me doy cuenta de que ha pasado un tiempo desde que ha habido alguna actividad nueva en esta cuestión. Pero, como han comentado otros carteles, get_result() ahora solo está disponible en PHP instalando el controlador nativo de MySQL (mysqlnd) y, en algunos casos, puede que no sea posible o deseable instalar mysqlnd. Por lo tanto, pensé que sería útil publicar esta respuesta con información sobre cómo obtener la funcionalidad que ofrece get_result() sin usar get_result() .

get_result() es / a menudo se combinó con fetch_array() para recorrer un conjunto de resultados y almacenar los valores de cada fila del conjunto de resultados en una matriz indexada numéricamente o asociativa. Por ejemplo, el siguiente código usa get_result () con fetch_array () para recorrer un conjunto de resultados, almacenando los valores de cada fila en la matriz indexada numéricamente $ data []:

$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"; }

Sin embargo, si get_result() no está disponible (porque mysqlnd no está instalado), esto lleva al problema de cómo almacenar los valores de cada fila de un conjunto de resultados en una matriz, sin usar get_result() . O bien, cómo migrar el código heredado que usa get_result() para ejecutar sin él (por ejemplo, usar bind_result() ) mientras impacta el resto del código lo menos posible.

Resulta que almacenar los valores de cada fila en una matriz indexada numéricamente no es tan directo usando bind_result() . bind_result() espera una lista de variables escalares (no una matriz). Por lo tanto, hace falta algo para que almacene los valores de cada fila del conjunto de resultados en una matriz.

Por supuesto, el código podría modificarse fácilmente de la siguiente manera:

$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"; }

Pero esto requiere que bind_result() explícitamente $ data [0], $ data [1], etc. individualmente en la llamada a bind_result() , lo cual no es ideal. Queremos una solución que no requiera que tengamos que listar explícitamente $ data [0], $ data [1], ... $ data [N-1] (donde N es el número de campos en la instrucción select) en la llamada a bind_results() . Si estamos migrando una aplicación heredada que tiene una gran cantidad de consultas, y cada consulta puede contener un número diferente de campos en la cláusula de select , la migración será muy laboriosa y propensa a error si usamos una solución como la encima.

Idealmente, queremos un fragmento de código de ''sustitución inmediata'' para reemplazar solo la línea que contiene la función get_result() y el ciclo while () en la siguiente línea. El código de reemplazo debe tener la misma función que el código que está reemplazando, sin afectar a ninguna de las líneas anteriores, ni a ninguna de las líneas posteriores, incluidas las líneas dentro del ciclo while (). Idealmente, queremos que el código de reemplazo sea lo más compacto posible, y no queremos tener que personalizar el código de reemplazo en función del número de campos en la cláusula de select de la consulta.

Al buscar en Internet, encontré una serie de soluciones que usan bind_param() con call_user_func_array() (por ejemplo, vincula dinámicamente los parámetros mysqli_stmt y luego vincula el resultado (PHP) ), pero la mayoría de las soluciones que encuentro conducen finalmente a que se almacenen los resultados en una matriz asociativa, no en una matriz indexada numéricamente, y muchas de estas soluciones no eran tan compactas como me gustaría y / o no eran adecuadas como ''reemplazos directos''. Sin embargo, de los ejemplos que encontré, pude improvisar esta solución, que se ajusta a la ley:

$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"; }

Por supuesto, el bucle for () puede colapsarse en una línea para hacerlo más compacto.

Espero que esto ayude a cualquiera que esté buscando una solución usando bind_result() para almacenar los valores de cada fila en una matriz indexada numéricamente y / o buscando una forma de migrar el código heredado usando get_result() . Comentarios bienvenidos.



Sé que esto ya fue respondido en cuanto a cuál es el problema real, sin embargo, quiero ofrecer una solución alternativa.

Quería usar el método get_results (), sin embargo, no tenía el controlador, y no estoy en un sitio que pueda agregar. Entonces, antes de llamar

$stmt->bind_results($var1,$var2,$var3,$var4...etc);

Creé una matriz vacía y luego limité los resultados como claves en esa matriz:

$result = array(); $stmt->bind_results($result[''var1''],$result[''var2''],$result[''var3''],$result[''var4'']...etc);

para que esos resultados puedan pasarse fácilmente a métodos o emitirse a un objeto para su uso posterior.

Espero que esto ayude a cualquiera que esté buscando hacer algo similar.


para aquellos que buscan una alternativa a $ result = stmt-> get_result () He creado esta función que te permite imitar $ result-> fetch_assoc () pero usando directamente el objeto stmt:

function fetchAssocStatement($stmt) { if($stmt->num_rows>0) { $result = array(); $md = $stmt->result_metadata(); $params = array(); while($field = $md->fetch_field()) { $params[] = &$result[$field->name]; } call_user_func_array(array($stmt, ''bind_result''), $params); if($stmt->fetch()) return $result; } return null; }

como puede ver, crea una matriz y la recupera con los datos de la fila, ya que usa $ stmt-> fetch () internamente, puede llamarla como llamaría a mysqli_result :: fetch_assoc (solo asegúrese de que el objeto $ stmt está abierto y el resultado está almacenado):

//mysqliConnection is your mysqli connection object if($stmt = $mysqli_connection->prepare($query)) { $stmt->execute(); $stmt->store_result(); while($assoc_array = fetchAssocStatement($stmt)) { //do your magic } $stmt->close(); }

espero que esto ayude.


¡Su sistema no tiene el controlador mysqlnd!

Si puede instalar paquetes nuevos en su servidor (basado en Debian / Ubuntu), instale el controlador:

sudo apt-get install php5-mysqlnd

y luego reinicia tu servidor web:

sudo /etc/init.d/apache2 restart