web-dev-qa-db-fra.com

Appel de la méthode non définie mysqli_stmt :: get_result

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

J'obtiens l'erreur sur la dernière ligne en tant que: Appel à la méthode non définie mysqli_stmt :: get_result ()

Voici le code pour 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 j'écris cette ligne:

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

Il imprime 'Déclaration NON préparée'. Si j'exécute la requête directement dans les IDE en remplaçant? Par des marques, cela fonctionne correctement. Veuillez noter que l'objet $ conn fonctionne correctement dans les autres requêtes du projet.

Toute aide s'il vous plaît .......

104
kush.impetus

Veuillez lire les notes de l'utilisateur pour cette méthode:

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

Il nécessite le pilote mysqlnd ... s'il n'est pas installé sur votre espace web, vous devrez travailler avec BIND_RESULT & FETCH!

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

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

141
bekay

Donc, si le pilote MySQL Native Driver (mysqlnd) n'est pas disponible, et donc en utilisant bind_result et fetch au lieu de get_result, le code devient:

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();
45
Bert Regelink

Votre système manque le pilote mysqlnd!

Si vous pouvez installer de nouveaux paquets sur votre serveur (basé sur Debian/Ubuntu), installez le pilote:

Sudo apt-get install php5-mysqlnd

puis redémarrez votre serveur Web:

Sudo /etc/init.d/Apache2 restart
42
M_R_K

pour ceux qui recherchent une alternative à $ result = stmt-> get_result (), j'ai créé cette fonction qui vous permet d'imiter $ result-> fetch_assoc () mais en utilisant directement l'objet 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;
}

comme vous pouvez le voir, il crée un tableau et le récupère avec les données de la ligne, puisqu'il utilise $ stmt-> fetch () en interne, vous pouvez l'appeler comme vous le feriez avec mysqli_result :: fetch_assoc (assurez-vous simplement que l'objet $ stmt est ouvert et le résultat est enregistré):

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

j'espère que cela t'aides.

37
MasterKitano

Je sais que le problème actuel a déjà été résolu, mais je souhaite proposer une solution de contournement simple.

Je voulais utiliser la méthode get_results (), mais je n'avais pas le pilote, et je ne suis pas un endroit où je peux l'obtenir. Donc, avant d'appeler

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

J'ai créé un tableau vide, puis j'ai simplement lié les résultats sous forme de clés dans ce tableau:

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

afin que ces résultats puissent facilement être transférés dans des méthodes ou convertis en un objet pour une utilisation ultérieure.

J'espère que cela aidera tous ceux qui cherchent à faire quelque chose de similaire.

10
Kirkland

Avec PHP version 7.2, je viens d'utiliser nd_mysqli au lieu de mysqli et cela a fonctionné comme prévu.

Étapes pour l'activer dans le serveur d'hébergement GoDaddy

  1. Connectez-vous à cpanel.
  2. Cliquez sur "Sélectionnez PHP version" .
  3. Comme fourni, l'instantané des dernières configurations décochez "mysqli" et activez "nd_mysqli" .

enter image description here

8
IRSHAD

Je recevais cette même erreur sur mon serveur - PHP 7.0 avec l'extension mysqlnd déjà activée.

La solution était pour moi (grâce à cette page ) de désélectionner l'extension mysqli et de sélectionner nd_mysqli à la place.

NB - Vous pourrez peut-être accéder au sélecteur d’extensions dans votre cPanel. (J'accède au mien via l'option . Sélectionnez PHP Version .).

7
ban-geoengineering

Je me rends compte que cela fait longtemps qu'il n'y a pas eu de nouvelle activité sur cette question. Mais, comme d'autres commentateurs l'ont commenté, get_result() n'est plus disponible que dans PHP en installant le pilote natif MySQL (mysqlnd), et dans certains cas, cela peut ne pas être possible. ou souhaitable d'installer mysqlnd. J'ai donc pensé qu'il serait utile de poster cette réponse avec des informations sur la façon d'obtenir la fonctionnalité proposée par get_result() - sans utiliser get_result().

get_result() est/était souvent combiné à fetch_array() pour parcourir un jeu de résultats et stocker les valeurs de chaque ligne du jeu de résultats dans un tableau associatif ou à index numérique. Par exemple, le code ci-dessous utilise get_result () avec fetch_array () pour parcourir un jeu de résultats en stockant les valeurs de chaque ligne du tableau $ data [] indexé numériquement:

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

Cependant, si get_result() n'est pas disponible (car mysqlnd n'est pas installé), le problème est de savoir comment stocker les valeurs de chaque ligne d'un jeu de résultats dans un tableau, sans utiliser get_result(). Ou comment migrer du code hérité qui utilise get_result() pour s'exécuter sans lui (par exemple, en utilisant bind_result() à la place) - tout en impactant le moins possible le reste du code.

Il s'avère que stocker les valeurs de chaque ligne dans un tableau indexé numériquement n'est pas aussi simple en utilisant bind_result(). bind_result() attend une liste de variables scalaires (pas un tableau). Donc, il faut faire quelque chose pour lui faire stocker les valeurs de chaque ligne du jeu de résultats dans un tableau.

Bien sûr, le code pourrait facilement être modifié comme suit:

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

Mais cela nous oblige à lister explicitement $ data [0], $ data [1], etc. individuellement dans l'appel à bind_result(), ce qui n'est pas idéal. Nous voulons une solution qui ne nous oblige pas à lister explicitement $ data [0], $ data [1], ... $ data [N-1] (où N est le nombre de champs de l'instruction select) dans l'appel à bind_results(). Si nous migrons une application héritée qui contient un grand nombre de requêtes et que chaque requête peut contenir un nombre différent de champs dans la clause select, la migration nécessitera beaucoup de main-d'oeuvre et d'erreur, si nous utilisons une solution comme celle ci-dessus.

Idéalement, nous voulons un extrait de code de "remplacement instantané" - pour remplacer uniquement la ligne contenant la fonction get_result() et la boucle while () sur la ligne suivante. Le code de remplacement doit avoir la même fonction que le code qu'il remplace, sans affecter les lignes précédentes, ni les lignes suivantes - y compris les lignes à l'intérieur de la boucle while (). Idéalement, nous souhaitons que le code de remplacement soit aussi compact que possible et nous ne voulons pas avoir à le tester en fonction du nombre de champs de la clause select de la requête.

En cherchant sur Internet, j'ai trouvé un certain nombre de solutions qui utilisent bind_param() avec call_user_func_array() (par exemple, lie dynamiquement les paramètres mysqli_stmt, puis lie le résultat (PHP) ), mais la plupart des solutions que j’ai trouvées aboutissaient finalement au stockage des résultats dans un tableau associatif, et non pas un tableau à index numérique, et nombre de ces solutions n’étaient pas aussi compactes que je le souhaiterais et/ou ne convenaient pas en remplacements ". Cependant, à partir des exemples que j'ai trouvés, j'ai pu combiner cette solution qui convient parfaitement:

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

Bien entendu, la boucle for () peut être réduite en une seule ligne pour la rendre plus compacte.

J'espère que cela aidera tous ceux qui recherchent une solution utilisant bind_result() à stocker les valeurs de chaque ligne dans un tableau indexé numériquement et/ou à la recherche d'un moyen de migrer le code hérité à l'aide de get_result(). Commentaires bienvenus.

6
mti2935

Voici mon alternative. C'est orienté objet et ressemble plus à 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();
    }
}

Usage:

$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
5
fzyzcjy

J'ai écrit deux fonctions simples qui donnent les mêmes fonctionnalités que $stmt->get_result();, mais elles ne nécessitent pas le pilote mysqlnd.

Vous simplement remplacer

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

et

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

(Pour obtenir le nombre de lignes renvoyées, vous pouvez utiliser $stmt->num_rows.)

Il vous suffit de placez ces deux fonctions J'ai écrit quelque part dans votre PHP Script. (Par exemple, tout en bas)

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

Comment ça marche :

Mon code utilise la fonction $stmt->result_metadata(); pour déterminer le nombre et le type de champs renvoyés, puis lie automatiquement les résultats récupérés à des références pré-créées. Fonctionne comme un charme!

2
Stefan S.