web-dev-qa-db-ja.com

未定義のメソッドmysqli_stmt :: get_resultの呼び出し

ここに私のコードがあります:

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

最終行にエラーが表示されます:未定義メソッドmysqli_stmt :: get_result()の呼び出し

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

この行を書くと:

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

'Statement NOT prepared'と出力されます。 IDE置換で直接クエリを実行すると?値でマークすると、正常に動作します。プロジェクトの他のクエリで$ connオブジェクトが正常に機能することに注意してください。

助けてください.......

104
kush.impetus

この方法のユーザーノートをお読みください。

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

Mysqlndドライバーが必要です... Webスペースにインストールされていない場合は、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

したがって、MySQL Native Driver(mysqlnd)ドライバーが利用できないため、get_resultの代わりにbind_resultおよびfetchを使用すると、コードは次のようになります。

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

システムにmysqlndドライバーがありません!

(Debian/Ubuntuベースの)サーバーに新しいパッケージをインストールできる場合は、ドライバーをインストールします。

Sudo apt-get install php5-mysqlnd

次に、Webサーバーを再起動します。

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

$ result = stmt-> get_result()の代替を探している人のために、$ result-> fetch_assoc()を模倣できるが、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;
}

ご覧のとおり、配列を作成し、行データでフェッチします。内部で$ stmt-> fetch()を使用しているため、mysqli_result :: fetch_assocを呼び出すのと同じように呼び出すことができます($ stmtオブジェクト開いており、結果が保存されています):

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

お役に立てれば。

37
MasterKitano

私はこれが実際の問題が何であるかについてすでに回答されていることを知っていますが、簡単な回避策を提供したいと思います。

Get_results()メソッドを使用したかったのですが、ドライバーを持っていなかったため、追加することができません。だから、電話する前に

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

空の配列を作成し、その配列のキーとして結果をバインドしました。

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

これらの結果を簡単にメソッドに渡したり、さらに使用するためにオブジェクトにキャストしたりできます。

これが似たようなことをしたい人に役立つことを願っています。

10
Kirkland

PHPバージョン7.2では、mysqliの代わりにnd_mysqliを使用しましたが、期待どおりに機能しました。

Godaddyホスティングサーバーで有効にする手順-

  1. Cpanelにログインします。
  2. 「Select PHP version」をクリックします。
  3. 提供されているように、最新の構成のスナップショットは "mysqli"のチェックを外し、有効にします "nd_mysqli"

enter image description here

8
IRSHAD

私のサーバーでも同じエラーが発生していました-PHP 7.0mysqlnd拡張機能は既に有効になっています。

私にとっては解決策でした( このページ のおかげで)mysqli拡張機能の選択を解除してnd_mysqli代わりに。

注意-cPanelの拡張機能セレクタにアクセスできる場合があります。 (Select PHP Versionオプション経由でアクセスします。)

7

この質問に関する新しい活動があったので、それはしばらくしていたことを認識しています。しかし、他のポスターがコメントしているように-get_result()はMySQLネイティブドライバー(mysqlnd)をインストールすることでPHPでのみ利用可能になり、場合によってはmysqlndのインストールが不可能または望ましくない場合があります。ですから、get_result()を使用せずにget_result()が提供する機能を取得する方法に関する情報をこの回答に投稿すると役立つと思いました。

get_result()は、結果セットをループし、結果セットの各行の値を数値インデックス付き配列または連想配列に格納するために、fetch_array()と組み合わせられることがよくあります。たとえば、次のコードでは、get_result()とfetch_array()を使用して結果セットをループし、各行の値を数値インデックス付きの$ 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"; 
}

ただし、get_result()が使用できない場合(mysqlndがインストールされていないため)、get_result()を使用せずに、結果セットの各行の値を配列に格納する方法の問題につながります。または、get_result()を使用するレガシーコードを移行せずに実行する方法(たとえば、代わりにbind_result()を使用)-残りのコードにはできるだけ影響を与えません。

bind_result()を使用して、数値インデックスの配列に各行の値を格納するのはそれほど簡単ではないことがわかります。 bind_result()は、配列ではなくスカラー変数のリストを想定しています。そのため、結果セットの各行の値を配列に保存するためには、ある程度の作業が必要です。

もちろん、コードは次のように簡単に変更できます。

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

ただし、これにはbind_result()の呼び出しで$ data [0]、$ data [1]などを個別に明示的にリストする必要がありますが、これは理想的ではありません。 $ data [0]、$ data [1]、... $ data [N-1](Nはselectステートメントのフィールド数)を明示的にリストする必要のないソリューションが必要です。 bind_results()への呼び出しで。多数のクエリを含むレガシーアプリケーションを移行し、各クエリにselect句に異なる数のフィールドが含まれる場合、非常に労働集約的であり、使用するとエラーが発生しやすくなります。上記のようなソリューション。

理想的には、「ドロップイン置換」コードのスニペットが必要です-get_result()関数と次の行のwhile()ループを含む行のみを置換します。置換コードは、置換するコードと同じ機能を持ち、while()ループ内の行を含む、前の行または後の行に影響を与えません。理想的には、置換コードを可能な限りコンパクトにし、クエリのselect句のフィールド数に基づいて置換コードを調整する必要はありません。

インターネットで検索すると、bind_param()call_user_func_array()を使用する多くのソリューション(たとえば、 mysqli_stmtパラメーターを動的にバインドし、結果(PHP)をバインドする )が見つかりましたが、最終的に私が見つけた解決策は、数値インデックスの配列ではなく連想配列に保存される結果につながり、これらの解決策の多くは私が望むほどコンパクトではなく、「ドロップイン置換」としては適していませんでしたしかし、私が見つけた例から、私はこの解決策をまとめることができました。

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

もちろん、for()ループを1行にまとめて、よりコンパクトにすることができます。

これが、bind_result()を使用して数値インデックス配列に各行の値を格納するソリューションを探している人や、get_result()を使用してレガシーコードを移行する方法を探している人に役立つことを願っています。コメントを歓迎します。

6
mti2935

これが私の代替案です。これはobject-orientedであり、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();
    }
}

使用法:

$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

$stmt->get_result();と同じ機能を提供する2つの単純な関数を作成しましたが、mysqlndドライバーは必要ありません。

あなたは単にreplace

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

および

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

(返された行の数を取得するには、$stmt->num_rowsを使用できます。)

これら2つの関数を配置する私はPHPスクリプトのどこかと書きました。 (たとえば、右下)

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

仕組み

私のコードは$stmt->result_metadata();関数を使用して、返されるフィールドの数と数を把握し、フェッチされた結果を事前に作成された参照に自動的にバインドします。チャームのように機能します!

2
Stefan S.