Aufruf der undefinierten Methode mysqli_stmt :: get_result

113

Hier ist mein Code:

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

Ich erhalte den Fehler in der letzten Zeile wie folgt: Aufruf der undefinierten Methode mysqli_stmt :: get_result ()

Hier ist der Code für 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();
        }
    }
}

Wenn ich diese Zeile schreibe:

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

Es wird "Erklärung NICHT vorbereitet" gedruckt . Wenn ich die Abfrage direkt in der IDE ersetze? Markierungen mit Werten, es funktioniert gut. Bitte beachten Sie, dass das Objekt $ conn in anderen Abfragen im Projekt einwandfrei funktioniert.

Jede Hilfe bitte .......

Kumar Kush
quelle
Ich denke du hast es vergessen $stmt = $conn->mysqli->stmt_init();?
favoretti
Bitte überprüfen Sie, ob diese Variablen $_POST['EmailID'], $_POST['SLA'], $_POST['Password']mithilfe eines HTML-Formulars mit POST-Methode korrekt übermittelt wurden
ajreal
@ajreal: Die Variablen werden korrekt gebucht. Ich habe sie mit print_r ($ _ POST) getestet.
Kumar Kush
@favoretti: Ich habe versucht, $ stmt = $ conn-> mysqli-> stmt_init () zu verwenden. . Immer noch kein Glück.
Kumar Kush
Eine Sache, die ich erwähnen möchte, ist, dass ich ähnlichen Code an anderen Stellen verwendet habe und sie gut funktionieren.
Kumar Kush

Antworten:

145

Bitte lesen Sie die Benutzerhinweise zu dieser Methode:

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

Es erfordert den mysqlnd-Treiber ... wenn er nicht auf Ihrem Webspace installiert ist, müssen Sie mit BIND_RESULT & FETCH arbeiten!

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

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

bekay
quelle
4
Vielen Dank. Das hat funktioniert. Ich habe die Erweiterung = php_mysqli_mysqlnd.dll in php.ini auskommentiert . und Apache2.2 und MySQL-Dienste neu gestartet. Sollte ich die Zeilenerweiterung = php_mysqli_libmysql.dll auskommentieren ? Laut einer anderen Seite ist mysqlnd schneller als libmysql. Kann ich auch erwarten, dass mysqlnd auf den meisten gängigen Hosting-Dienstleistern installiert ist?
Kumar Kush
1
stmt_init () wird nur für eine prozedural vorbereitete Anweisung benötigt. du brauchst es also nicht! Look: link Wie für die libmysql : weiß nicht. Und ich würde nicht auf Hosting-Anbieter für die Installation von mysqlnd.dll zählen ... versuchen Sie besser eine Problemumgehung !
bekay
2
Hinweis: mysqli_stmt::get_result()ist nur unter PHP v5.3.0 oder höher verfügbar.
Raptor
4
@bekay Du hast mir gerade einen neuen Laptop und ein neues Fenster gerettet. Wenn +10 verfügbar wäre, würde ich es Ihnen geben
James Cushing
1
@ kush.impetus, Wo lädst du herunter php_mysqli_mysqlnd.dll? Ich hätte nur php_mysqli.dllin meinem extOrdner.
Pacerier
51

Wenn der MySQL Native Driver (mysqlnd) -Treiber nicht verfügbar ist und daher bind_result und fetch anstelle von get_result verwendet , lautet der Code wie folgt :

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
quelle
$ stmt-> bind_result spart mir Zeit. Es ist eine großartige Lösung, wenn get_result nicht verfügbar ist.
Zafer
2
Frage: Woher kommt die Variable $ EmailVerfied?
Rotimi
@ Akintunde007: $EmailVerfiedwird durch den Aufruf von erstellt bind_result().
AbraCadaver
Erhalten eines "Nicht gefangenen Fehlers: Aufruf der undefinierten Methode mysqli_stmt :: bind_results ()" Fehler unter Verwendung des Codes
Devil's Dream
Wenn ich eine SQL-Abfrage wie "Select * from table_name" habe, dann wie in bind_result () deklarieren. * Betreiber
Inderjeet
46

Ihrem System fehlt der mysqlnd-Treiber!

Wenn Sie neue Pakete auf Ihrem (Debian / Ubuntu-basierten) Server installieren können, installieren Sie den Treiber:

sudo apt-get install php5-mysqlnd

und starten Sie dann Ihren Webserver neu:

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

Für diejenigen, die nach einer Alternative suchen, $result = $stmt->get_result()habe ich diese Funktion entwickelt, mit der Sie $result->fetch_assoc()das stmt-Objekt nachahmen können, aber direkt verwenden:

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

Wie Sie sehen, wird ein Array erstellt und mit den Zeilendaten abgerufen. Da es $stmt->fetch()intern verwendet wird, können Sie es so aufrufen, wie Sie es aufrufen würden mysqli_result::fetch_assoc(stellen Sie nur sicher, dass das $stmtObjekt geöffnet ist und das Ergebnis gespeichert ist):

//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
quelle
Dies ist hier die einfachste Ersatzantwort. Hat super funktioniert - danke!
Alex Coleman
Hat mir viel Zeit gespart!
Jahaziel
3
Wenn dies $statement->store_result();vor dem Aufruf der Funktion erforderlich ist, können Sie es einfach in die Funktion aufnehmen.
InsanityOnABun
Danke dir. Gerade meinen Arsch auf eine Frist gerettet
Kolob Canyon
20

Mit PHP Version 7.2 habe ich nur nd_mysqli anstelle von mysqli verwendet und es hat wie erwartet funktioniert.

Schritte, um es in Godaddy Hosting Server zu aktivieren-

  1. Melden Sie sich bei cpanel an.
  2. Klicken Sie auf "PHP-Version auswählen" .
  3. Deaktivieren Sie wie angegeben den Snapshot der neuesten Konfigurationen "mysqli" und aktivieren Sie "nd_mysqli" .

Geben Sie hier die Bildbeschreibung ein

IRSHAD
quelle
2
Danke, ich wurde verrückt!
Ussaid Iqbal
1
Haaa, das spart mir Zeit! Danke broh!
Nurul Huda
1
großartig! perfekte Antwort für cPanel
Rashid
1
Ich danke dir sehr!! Du rettest mich, Mann, ich kann dir nicht genug danken
Enes Çalışkan
Diese Antwort sollte oben sein
Rishabh Gusain
10

Ich weiß, dass dies bereits beantwortet wurde, was das eigentliche Problem ist, aber ich möchte eine einfache Problemumgehung anbieten.

Ich wollte die Methode get_results () verwenden, hatte aber keinen Treiber, und ich bin nicht irgendwo, wo ich das hinzufügen kann. Also, bevor ich anrief

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

Ich habe ein leeres Array erstellt und dann die Ergebnisse als Schlüssel in diesem Array gebunden:

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

so dass diese Ergebnisse leicht an Methoden übergeben oder zur weiteren Verwendung in ein Objekt umgewandelt werden können.

Hoffe, das hilft jedem, der etwas Ähnliches tun möchte.

Kirkland
quelle
7

Ich habe den gleichen Fehler auf meinem Server erhalten - PHP 7.0 mit der bereits aktivierten Erweiterung mysqlnd .

Lösung war für mich (dank dieser Seite ) war die abzuwählen mysqli Erweiterung und wählen Sie nd_mysqli statt.

NB - Möglicherweise können Sie auf die Erweiterungsauswahl in Ihrem cPanel zugreifen. (Ich greife über die Option PHP-Version auswählen auf meine zu .)

Ban-Geoengineering
quelle
Dies sollte die akzeptierte Antwort sein. Es ist viel besser, die Erweiterung zu aktivieren, als das gesamte Skript zu bearbeiten, um eine andere Methode zu verwenden! Oh und es hat bei mir funktioniert :)
ArabianMaiden
Ich hatte das gleiche Problem. Tatsächlich session_start()machte mich die Verwendung der PHP- Funktion zu einem nicht existierenden Wert. Dann habe ich auf 7.2PHP aktualisiert und die Erweiterung von mysqliauf nd_mysqli (behoben) geändert . Aber ich habe zwei Fragen, was ist der Unterschied zwischen den beiden? und ob es eine Sicherheitslücke für die Verwendung dieser Erweiterung geben würde?
Jecorrales
6

Mir ist klar, dass es eine Weile her ist, dass es zu dieser Frage neue Aktivitäten gegeben hat. Aber, wie andere Poster kommentiert haben, get_result()ist es jetzt nur in PHP verfügbar, indem der native MySQL-Treiber (mysqlnd) installiert wird. In einigen Fällen ist es möglicherweise nicht möglich oder wünschenswert, mysqlnd zu installieren. Daher dachte ich, es wäre hilfreich, diese Antwort mit Informationen darüber zu veröffentlichen, wie Sie die angebotenen Funktionen erhalten get_result()- ohne sie zu verwenden get_result().

get_result()wird / wurde oft kombiniert fetch_array(), um eine Ergebnismenge zu durchlaufen und die Werte aus jeder Zeile der Ergebnismenge in einem numerisch indizierten oder assoziativen Array zu speichern. Im folgenden Code wird beispielsweise get_result () mit fetch_array () verwendet, um eine Ergebnismenge zu durchlaufen und die Werte aus jeder Zeile im numerisch indizierten Array $ data [] zu speichern:

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

Wenn dies get_result()jedoch nicht verfügbar ist (da mysqlnd nicht installiert ist), führt dies zu dem Problem, wie die Werte aus jeder Zeile einer Ergebnismenge in einem Array ohne Verwendung gespeichert werden können get_result(). Oder wie man alten Code migriert, der verwendet wird get_result(), um ohne ihn ausgeführt zu werden (z. B. bind_result()stattdessen), während der Rest des Codes so wenig wie möglich beeinflusst wird.

Es stellt sich heraus, dass das Speichern der Werte aus jeder Zeile in einem numerisch indizierten Array nicht so einfach ist bind_result(). bind_result()erwartet eine Liste skalarer Variablen (kein Array). Es ist also einige Arbeit erforderlich, um die Werte aus jeder Zeile der Ergebnismenge in einem Array zu speichern.

Natürlich kann der Code leicht wie folgt geändert werden:

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

Dies erfordert jedoch, dass wir $ data [0], $ data [1] usw. im Aufruf von explizit einzeln auflisten bind_result(), was nicht ideal ist. Wir wollen eine Lösung, bei der wir nicht explizit $ data [0], $ data [1], ... $ data [N-1] auflisten müssen (wobei N die Anzahl der Felder in der select-Anweisung ist). im Anruf an bind_results(). Wenn wir eine Legacy-Anwendung mit einer großen Anzahl von Abfragen migrieren und jede Abfrage möglicherweise eine andere Anzahl von Feldern in der selectKlausel enthält, ist die Migration sehr arbeitsintensiv und fehleranfällig, wenn wir eine Lösung wie die oben beschriebene verwenden .

Idealerweise möchten wir einen Ausschnitt aus dem Drop-In-Ersetzungscode, um nur die Zeile zu ersetzen, die die get_result()Funktion und die while () -Schleife in der nächsten Zeile enthält. Der Ersetzungscode sollte dieselbe Funktion haben wie der Code, den er ersetzt, ohne die Zeilen davor oder die Zeilen danach zu beeinflussen - einschließlich der Zeilen innerhalb der while () - Schleife. Idealerweise möchten wir, dass der Ersatzcode so kompakt wie möglich ist, und wir möchten nicht, dass der Ersatzcode basierend auf der Anzahl der Felder in der selectKlausel der Abfrage angepasst wird.

Bei der Suche im Internet habe ich eine Reihe von Lösungen gefunden, die bind_param()mit call_user_func_array() (z. B. dynamisch mysqli_stmt-Parameter binden und dann Ergebnis binden (PHP) ) verwendet werden. Die meisten Lösungen, die ich gefunden habe, führen jedoch dazu, dass die Ergebnisse in einem assoziativen Array gespeichert werden, nicht ein numerisch indiziertes Array, und viele dieser Lösungen waren nicht so kompakt, wie ich es gerne hätte, und / oder waren nicht als "Drop-In-Ersatz" geeignet. Aus den Beispielen, die ich gefunden habe, konnte ich jedoch diese Lösung zusammenschustern, die der Rechnung entspricht:

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

Natürlich kann die for () - Schleife in einer Zeile zusammengefasst werden, um sie kompakter zu machen.

Ich hoffe, dies hilft jedem, der nach einer Lösung sucht, mit der bind_result()er die Werte aus jeder Zeile in einem numerisch indizierten Array speichert und / oder nach einer Möglichkeit sucht, Legacy-Code mithilfe von zu migrieren get_result(). Kommentare willkommen.

mti2935
quelle
Yupp. Vor 3 Jahren auf gU umgestellt. Trotzdem danke.
Kumar Kush
5

Hier ist meine Alternative. Es ist objektorientiert und ähnelt eher MySQL / Mysqli-Dingen.

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

Verwendung:

$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
quelle
2

Ich habe zwei einfache Funktionen geschrieben, die die gleiche Funktionalität $stmt->get_result();bieten wie , aber den mysqlnd-Treiber nicht benötigen.

Sie ersetzen einfach

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

und

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

(Um die Anzahl der zurückgegebenen Zeilen zu ermitteln, können Sie diese verwenden $stmt->num_rows.)

Sie müssen nur diese beiden Funktionen platzieren, die ich irgendwo in Ihrem PHP-Skript geschrieben habe . (zum Beispiel ganz unten)

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

Wie es funktioniert :

Mein Code verwendet die $stmt->result_metadata();Funktion, um herauszufinden, wie viele und welche Felder zurückgegeben werden, und bindet dann die abgerufenen Ergebnisse automatisch an vorab erstellte Referenzen. Klappt wunderbar!

Stefan S.
quelle
Keine Ahnung, warum es abgelehnt wurde. Es funktioniert sehr gut - ich habe es in vielen Projekten verwendet.
Stefan S.