Llamada al método indefinido mysqli_stmt :: get_result

113

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

Recibo 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 del proyecto.

Cualquier ayuda por favor .......

Kumar Kush
fuente
Creo que se le olvidó $stmt = $conn->mysqli->stmt_init();?
favoretti
Verifique si estas variables se $_POST['EmailID'], $_POST['SLA'], $_POST['Password']enviaron correctamente utilizando un formulario HTML con el método POST
ajreal
@ajreal: las variables se publican correctamente. Los probé usando print_r ($ _ POST).
Kumar Kush
@favoretti: Intenté usar $ stmt = $ conn-> mysqli-> stmt_init (); . Sigo sin suerte.
Kumar Kush
Una cosa que me gustaría mencionar es que he usado un código similar en otros lugares y funcionan bien.
Kumar Kush

Respuestas:

146

Lea las notas de usuario para este método:

http://php.net/manual/en/mysqli-stmt.get-result.php

Requiere el controlador mysqlnd ... si no está instalado en su espacio web, tendrá que trabajar con BIND_RESULT & FETCH.

https://secure.php.net/manual/en/mysqli-stmt.bind-result.php

https://secure.php.net/manual/en/mysqli-stmt.fetch.php

bekay
fuente
4
Muchas gracias. Eso funciono. Descomenté la extensión = php_mysqli_mysqlnd.dll en php.ini ; y reinició los servicios Apache2.2 y MySQL. ¿Debo descomentar la extensión de línea = php_mysqli_libmysql.dll ? Según otra página, mysqlnd es más rápido que libmysql. Además, ¿puedo esperar que mysqlnd esté instalado en los proveedores de servicios de alojamiento más populares?
Kumar Kush
1
stmt_init () solo es necesario para una declaración preparada de procedimiento. ¡así que no lo necesitas! Mira: enlace En cuanto a libmysql : no lo sé. Y no contaría con proveedores de hosting para la instalación de mysqlnd.dll ... ¡mejor prueba alguna solución!
bekay
2
Nota: mysqli_stmt::get_result()solo está disponible en PHP v5.3.0 o superior.
Raptor
4
@bekay Me acabas de guardar una nueva computadora portátil y una nueva ventana. Si +10 estuviera disponible, te lo daría
James Cushing
1
@ kush.impetus, ¿Dónde se descarga php_mysqli_mysqlnd.dll? Solo lo tendría php_mysqli.dllen mi extcarpeta.
Pacerier
51

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

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();
Bert Regelink
fuente
$ stmt-> bind_result me ​​ahorra tiempo. Es una gran solución cuando get_result no está disponible.
Zafer
2
pregunta: ¿de dónde viene la variable $ EmailVerfied?
Rotimi
@ Akintunde007: $EmailVerfiedse crea mediante la llamada a bind_result().
AbraCadaver
Obteniendo un error "No detectado: llamada al método indefinido mysqli_stmt :: bind_results ()" al usar el código
Devil's Dream
Si tengo una consulta sql como "Seleccionar * de table_name", entonces cómo declarar dentro de bind_result (). * operador
Inderjeet
46

¡A su sistema le falta el controlador mysqlnd!

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

sudo apt-get install php5-mysqlnd

y luego reinicie su servidor web:

sudo /etc/init.d/apache2 restart
M_R_K
fuente
39

para aquellos que buscan una alternativa a $result = $stmt->get_result(), hice esta función que le 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 obtiene con los datos de la fila, ya que se usa $stmt->fetch()internamente, puede llamarla tal como lo llamaría mysqli_result::fetch_assoc(solo asegúrese de que el $stmtobjeto 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();
}
MasterKitano
fuente
Esta es la respuesta de reemplazo más fácil aquí. Funcionó muy bien, ¡gracias!
Alex Coleman
¡Me ahorro mucho tiempo!
Jahaziel
3
Si $statement->store_result();es necesario antes de llamar a la función, ¿por qué no incluirla en la función?
InsanityOnABun
Gracias. Acabo de salvar mi trasero en una fecha límite
Kolob Canyon
20

Con PHP versión 7.2, utilicé nd_mysqli en lugar de mysqli y funcionó como se esperaba.

Pasos para habilitarlo en el servidor de alojamiento de godaddy

  1. Inicie sesión en cpanel.
  2. Haga clic en "Seleccionar versión de PHP" .
  3. Como se proporciona la instantánea de las últimas configuraciones, desmarque "mysqli" y habilite "nd_mysqli" .

ingrese la descripción de la imagen aquí

IRSHAD
fuente
2
¡Gracias, me estaba volviendo loco!
Ussaid Iqbal
1
¡Haaa, esto me ahorra tiempo! ¡Gracias hermano!
Nurul Huda
1
¡Excelente! respuesta perfecta para cPanel
Rashid
1
¡¡Muchas gracias!! Me salvas hombre, no puedo agradecerte lo suficiente
Enes Çalışkan
Esta respuesta debería estar en la parte superior
Rishabh Gusain
10

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

Quería usar el método get_results (), sin embargo, no tenía el controlador y no estoy en ningún lugar donde pueda agregarlo. Entonces, antes de llamar

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

Creé una matriz vacía y luego enlacé 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 convertirse en un objeto para su uso posterior.

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

Kirkland
fuente
7

Recibí este mismo error en mi servidor: PHP 7.0 con mysqlnd extensión ya habilitada.

La solución fue para mí (gracias a esta página ) fue deseleccionar la extensión mysqli y seleccionar nd_mysqli en su lugar.

NB - Es posible que pueda acceder al selector de extensiones en su cPanel. (Accedo al mío a través de la opción Seleccionar versión de PHP ).

ban-geoingeniería
fuente
Esta debería ser la respuesta aceptada. ¡Es mucho mejor habilitar la extensión que editar todo el script para usar otro método! Ah, y funcionó para mí :)
ArabianMaiden
Yo tuve el mismo problema. De hecho, usar la session_start()función de PHP me convirtió en un valor inexistente. Luego actualicé a la versión 7.2de PHP y cambié la extensión de mysqlia nd_mysqli (fijo). Pero tengo dos preguntas, ¿cuál es la diferencia entre las dos? y si habría alguna brecha en la seguridad para usar esa extensión?
jecorrales
6

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

get_result()es / se combinó a menudo con fetch_array()para recorrer un conjunto de resultados y almacenar los valores de cada fila del conjunto de resultados en una matriz asociativa o indexada numéricamente. 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 $ data [] indexada numéricamente:

$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 cómo migrar el código heredado que solía get_result()ejecutarse sin él (por ejemplo, usarlo en su bind_result()lugar), mientras afecta al resto del código lo menos posible.

Resulta que almacenar los valores de cada fila en una matriz indexada numéricamente no es tan sencillo de usar bind_result(). bind_result()espera una lista de variables escalares (no una matriz). Por lo tanto, se necesita algo de esfuerzo 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 enumeremos 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 enumerar explícitamente $ datos [0], $ datos [1], ... $ datos [N-1] (donde N es el número de campos en la declaración de selección) 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 una cantidad diferente de campos en elselect cláusula, la migración será muy laboriosa y propensa a errores si usamos una solución como la anterior. .

Idealmente, queremos un fragmento de código de 'reemplazo directo', para reemplazar solo la línea que contiene la get_result()función y el bucle 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 ninguna de las líneas anteriores o posteriores, incluidas las líneas dentro del bucle while (). Idealmente, queremos que el código de reemplazo sea lo más compacto posible, y no queremos tener que adaptar el código de reemplazo en función del número de campos en elselect cláusula de la consulta.

Buscando en Internet, encontré una serie de soluciones que se utilizan bind_param()con call_user_func_array() (por ejemplo, enlazar dinámicamente los parámetros mysqli_stmt y luego enlazar el resultado (PHP) ), pero la mayoría de las soluciones que encontré finalmente conducen a que los resultados se almacenen en una matriz asociativa, no 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, a partir de los ejemplos que encontré, pude improvisar esta solución, que se ajusta a los requisitos:

$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 ciclo for () se puede contraer en una línea para hacerlo más compacto.

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

mti2935
fuente
Sí. Cambiado a DOP hace 3 años. Gracias de todos modos.
Kumar Kush
5

Esta es mi alternativa. Está orientado a objetos y se parece más a 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
ch271828n
fuente
2

He escrito dos funciones simples que brindan 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 el número de filas devueltas, puede usar $stmt->num_rows).

Solo tiene que colocar estas dos funciones que he escrito en algún lugar de su script 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 la $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!

Stefan S.
fuente
No tengo idea de por qué se votó en contra. Funciona muy bien, lo he usado en muchos proyectos.
Stefan S.