Chiamata al metodo non definito mysqli_stmt :: get_result


113

Ecco il mio codice:

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

Ottengo l'errore sull'ultima riga come: Call to undefined method mysqli_stmt :: get_result ()

Ecco il codice per 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();
        }
    }
}

Se scrivo questa riga:

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

Stampa "Dichiarazione NON preparata" . Se eseguo la query direttamente nell'IDE sostituendo? segna con valori, funziona bene. Si noti che l'oggetto $ conn funziona correttamente in altre query nel progetto.

Qualsiasi aiuto per favore .......


Penso che ti sei dimenticato $stmt = $conn->mysqli->stmt_init();?
favoretti

Verifica che queste variabili siano $_POST['EmailID'], $_POST['SLA'], $_POST['Password']inviate correttamente utilizzando un modulo HTML con metodo POST
ajreal

@ajreal: le variabili vengono pubblicate correttamente. Li ho testati usando print_r ($ _ POST).
Kumar Kush

@favoretti: ho provato a usare $ stmt = $ conn-> mysqli-> stmt_init (); . Ancora senza fortuna.
Kumar Kush

Una cosa che vorrei menzionare è che ho usato un codice simile in altri posti e funzionano bene.
Kumar Kush

Risposte:


146

Si prega di leggere le note per l'utente per questo metodo:

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

Richiede il driver mysqlnd ... se non è installato sul tuo spazio web dovrai lavorare 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


4
Molte grazie. Ha funzionato. Ho decommentato l' estensione = php_mysqli_mysqlnd.dll in php.ini ; e riavviato i servizi Apache2.2 e MySQL. Devo rimuovere il commento dall'estensione di riga = php_mysqli_libmysql.dll ? Come per un'altra pagina, mysqlnd è più veloce di libmysql. Inoltre, posso aspettarmi che mysqlnd sia installato sui provider di servizi di hosting più popolari?
Kumar Kush

1
stmt_init () è necessario solo per un'istruzione preparata procedurale. quindi non ne hai bisogno! Guarda: link Per quanto riguarda libmysql : non lo so. E non conterei su provider di hosting per l'installazione di mysqlnd.dll ... meglio provare qualche soluzione alternativa!
bekay

2
Nota: mysqli_stmt::get_result()è disponibile solo su PHP v5.3.0 o superiore.
Raptor

4
@bekay Mi hai appena salvato un nuovo laptop e una nuova finestra. Se fosse disponibile +10 te lo darei
James Cushing

1
@ kush.impetus, dove scarichi php_mysqli_mysqlnd.dll? Avrei solo php_mysqli.dllnella mia extcartella.
Pacerier

51

Quindi, se il driver MySQL Native Driver (mysqlnd) non è disponibile, e quindi utilizzando bind_result e fetch invece di get_result , il codice diventa:

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

$ stmt-> bind_result mi fa risparmiare tempo. È un'ottima soluzione quando get_result non è disponibile.
Zafer

2
domanda: da dove viene la variabile $ EmailVerfied?
Rotimi

@ Akintunde007: $EmailVerfiedviene creato dalla chiamata a bind_result().
AbraCadaver

Ottenere un errore "Uncaught Error: Call to undefined method mysqli_stmt :: bind_results ()" errore utilizzando il codice
Devil's Dream

Se ho una query sql come "Seleziona * da table_name", allora come dichiarare all'interno di bind_result (). * operatore
Inderjeet

46

Nel tuo sistema manca il driver mysqlnd!

Se sei in grado di installare nuovi pacchetti sul tuo server (basato su Debian / Ubuntu), installa il driver:

sudo apt-get install php5-mysqlnd

e quindi riavvia il tuo server web:

sudo /etc/init.d/apache2 restart

39

per chi cerca un'alternativa a $result = $stmt->get_result()ho realizzato questa funzione che permette di imitare il $result->fetch_assoc()ma utilizzando direttamente l'oggetto 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;
}

come puoi vedere crea un array e lo recupera con i dati della riga, poiché utilizza $stmt->fetch()internamente, puoi chiamarlo proprio come lo chiameresti mysqli_result::fetch_assoc(assicurati solo che l' $stmtoggetto sia aperto e il risultato sia memorizzato):

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

Questa è la risposta sostitutiva più semplice qui. Ha funzionato alla grande, grazie!
Alex Coleman

Mi ha fatto risparmiare un sacco di tempo!
Jahaziel

3
Se $statement->store_result();è necessario prima di chiamare la funzione, perché non includerlo nella funzione?
InsanityOnABun

Grazie. Mi sono appena salvato il culo su una scadenza
Kolob Canyon

20

Con la versione 7.2 di PHP ho usato solo nd_mysqli invece di mysqli e ha funzionato come previsto.

Passaggi per abilitarlo nel server di hosting Godaddy-

  1. Accedi a cpanel.
  2. Fare clic su "Seleziona versione PHP" .
  3. Come fornito l'istantanea delle ultime configurazioni deselezionare "mysqli" e abilitare "nd_mysqli" .

inserisci qui la descrizione dell'immagine


2
Grazie, stavo impazzendo!
Ha detto Iqbal l'

1
Haaa, questo mi fa risparmiare tempo! Grazie broh!
Nurul Huda

1
grande! risposta perfetta per cPanel
Rashid

1
Grazie mille!! Mi salvi amico, non posso ringraziarti abbastanza
Enes Çalışkan

Questa risposta dovrebbe essere in cima
Rishabh Gusain

10

So che è già stato risposto a quale sia il problema reale, tuttavia voglio offrire una semplice soluzione alternativa.

Volevo usare il metodo get_results () ma non avevo il driver e non sono da qualche parte in cui posso aggiungerlo. Quindi, prima che chiamassi

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

Ho creato un array vuoto, quindi ho semplicemente associato i risultati come chiavi in ​​quell'array:

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

in modo che quei risultati possano essere facilmente passati in metodi o convertiti in un oggetto per un ulteriore utilizzo.

Spero che questo aiuti chiunque stia cercando di fare qualcosa di simile.


7

Stavo ricevendo lo stesso errore sul mio server: PHP 7.0 con l' estensione mysqlnd già abilitata.

La soluzione per me (grazie a questa pagina ) è stata deselezionare l' estensione mysqli e selezionare invece nd_mysqli .

NB - Potresti essere in grado di accedere al selettore delle estensioni nel tuo cPanel. (Accedo al mio tramite l' opzione Seleziona versione PHP .)


Questa dovrebbe essere la risposta accettata. Molto meglio abilitare l'estensione che modificare l'intero script per utilizzare un altro metodo! Oh, e ha funzionato per me :)
ArabianMaiden

Ho avuto lo stesso problema. In effetti, l'utilizzo della session_start()funzione di PHP mi ha reso un valore inesistente. Quindi ho aggiornato alla versione 7.2di PHP e ho cambiato l'estensione di mysqlia nd_mysqli (risolto). Ma ho due domande, qual è la differenza tra i due? e se ci fosse qualche lacuna nella sicurezza per l'utilizzo di tale estensione?
jecorrales

6

Mi rendo conto che è passato un po 'di tempo da quando non c'è stata alcuna nuova attività su questa questione. Ma, come hanno commentato altri utenti, get_result()ora è disponibile solo in PHP installando il driver nativo di MySQL (mysqlnd) e in alcuni casi potrebbe non essere possibile o desiderabile installare mysqlnd. Quindi, ho pensato che sarebbe stato utile pubblicare questa risposta con informazioni su come ottenere la funzionalità che get_result()offre, senza utilizzare get_result().

get_result()è / è stato spesso combinato con fetch_array()per scorrere un set di risultati e memorizzare i valori di ciascuna riga del set di risultati in un array numerico o associativo. Ad esempio, il codice seguente utilizza get_result () con fetch_array () per scorrere un set di risultati, memorizzando i valori di ogni riga nell'array $ data [] indicizzato numericamente:

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

Tuttavia, se get_result()non è disponibile (perché mysqlnd non è installato), allora questo porta al problema di come memorizzare i valori di ogni riga di un set di risultati in un array, senza utilizzare get_result(). Oppure, come migrare il codice legacy che utilizza get_result()per funzionare senza di esso (ad esempio utilizzandobind_result() invece), influendo il meno possibile sul resto del codice.

Risulta che memorizzare i valori di ogni riga in una matrice indicizzata numericamente non è così semplice da usare bind_result(). bind_result()si aspetta un elenco di variabili scalari (non un array). Quindi, ci vuole un po 'di tempo per far sì che memorizzi i valori di ogni riga del set di risultati in un array.

Ovviamente il codice potrebbe essere facilmente modificato come segue:

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

Ma questo ci richiede di elencare esplicitamente $ data [0], $ data [1], ecc. Individualmente nella chiamata a bind_result(), il che non è l'ideale. Vogliamo una soluzione che non richieda di dover elencare esplicitamente $ data [0], $ data [1], ... $ data [N-1] (dove N è il numero di campi nell'istruzione select) nella chiamata a bind_results(). Se stiamo migrando un'applicazione legacy che ha un numero elevato di query e ogni query può contenere un numero diverso di campi nelselect clausola, la migrazione sarà molto laboriosa e soggetta a errori se usiamo una soluzione come quella sopra .

Idealmente, vogliamo uno snippet di codice di "sostituzione immediata" - per sostituire solo la riga contenente la get_result()funzione e il ciclo while () sulla riga successiva. Il codice sostitutivo dovrebbe avere la stessa funzione del codice che sta sostituendo, senza influenzare nessuna delle righe precedenti o successive, comprese le righe all'interno del ciclo while (). Idealmente vogliamo che il codice sostitutivo sia il più compatto possibile e non vogliamo dover adattare il codice sostitutivo in base al numero di campi nella selectclausola della query.

Cercando su Internet, ho trovato una serie di soluzioni che utilizzano bind_param()con call_user_func_array() (ad esempio, Associa dinamicamente i parametri mysqli_stmt e poi associa il risultato (PHP) ), ma la maggior parte delle soluzioni che ho trovato alla fine porta a memorizzare i risultati in un array associativo, non un array a indice numerico e molte di queste soluzioni non erano così compatte come avrei voluto e / o non erano adatte come "sostituzioni immediate". Tuttavia, dagli esempi che ho trovato, sono stato in grado di mettere insieme questa soluzione, che si adatta al conto:

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

Ovviamente, il ciclo for () può essere compresso in una riga per renderlo più compatto.

Spero che questo aiuti chiunque stia cercando una soluzione che utilizzi bind_result()per memorizzare i valori di ogni riga in un array con indicizzazione numerica e / o che cerchi un modo per migrare il codice legacy utilizzando get_result(). Commenti benvenuti.


Yupp. Passato a DOP 3 anni fa. Grazie comunque.
Kumar Kush

5

Ecco la mia alternativa. È orientato agli oggetti ed è più simile 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

2

Ho scritto due semplici funzioni che danno la stessa funzionalità di $stmt->get_result();, ma non richiedono il driver mysqlnd.

Devi semplicemente sostituire

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

e

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

(Per ottenere il numero di righe restituite che puoi utilizzare $stmt->num_rows.)

Devi solo inserire queste due funzioni che ho scritto da qualche parte nel tuo script PHP . (ad esempio proprio in basso)

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

Come funziona :

Il mio codice utilizza la $stmt->result_metadata();funzione per capire quanti e quali campi vengono restituiti e quindi associa automaticamente i risultati recuperati a riferimenti pre-creati. Funziona come un fascino!


Non ho idea del perché sia ​​stato svalutato. Funziona molto bene: l'ho usato in molti progetti.
Stefan S.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.