Panggil ke metode yang tidak ditentukan mysqli_stmt :: get_result

113

Ini kode saya:

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

Saya mendapatkan kesalahan pada baris terakhir sebagai: Panggilan ke metode yang tidak ditentukan mysqli_stmt :: get_result ()

Berikut adalah kode untuk 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();
        }
    }
}

Jika saya menulis baris ini:

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

Ini mencetak 'Pernyataan TIDAK disiapkan' . Jika saya menjalankan kueri langsung di IDE menggantikan? menandai dengan nilai, itu berfungsi dengan baik. Harap dicatat bahwa objek $ conn berfungsi dengan baik di kueri lain dalam proyek ini.

Tolong bantu ...

Kumar Kush
sumber
Saya pikir Anda lupa $stmt = $conn->mysqli->stmt_init();?
favoretti
Harap periksa apakah variabel ini $_POST['EmailID'], $_POST['SLA'], $_POST['Password']dikirimkan dengan benar menggunakan formulir HTML dengan metode POST
ajreal
@ajreal: Variabel sedang diposting dengan benar. Saya mengujinya menggunakan print_r ($ _ POST).
Kumar Kush
@favoretti: Saya mencoba menggunakan $ stmt = $ conn-> mysqli-> stmt_init (); . Masih belum berhasil.
Kumar Kush
Satu hal yang ingin saya sebutkan adalah bahwa saya telah menggunakan kode serupa di tempat lain dan berfungsi dengan baik.
Kumar Kush

Jawaban:

146

Silakan baca catatan pengguna untuk metode ini:

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

Ini membutuhkan driver mysqlnd ... jika tidak diinstal pada ruang web Anda, Anda harus bekerja dengan 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
sumber
4
Terima kasih banyak. Itu berhasil. Saya menghapus komentar di extension = php_mysqli_mysqlnd.dll di php.ini ; dan memulai ulang layanan Apache2.2 dan MySQL. Haruskah saya menghapus komentar pada ekstensi baris = php_mysqli_libmysql.dll ? Untuk halaman lain, mysqlnd lebih cepat dari libmysql. Selain itu, dapatkah saya berharap mysqlnd diinstal pada penyedia layanan hosting paling populer?
Kumar Kush
1
stmt_init () hanya diperlukan untuk pernyataan prosedural yang disiapkan. jadi Anda tidak membutuhkannya! Lihat: link Adapun libmysql : tidak tahu. Dan saya tidak akan mengandalkan penyedia hosting untuk instalasi mysqlnd.dll ... lebih baik coba beberapa solusi!
bekay
2
Catatan: mysqli_stmt::get_result()hanya tersedia di PHP v5.3.0 atau lebih tinggi.
Raptor
4
@bekay Anda baru saja menyelamatkan saya laptop baru dan jendela baru. Jika +10 tersedia, saya akan memberikannya
James Cushing
1
@ kush.impetus, Dimana anda mendownload php_mysqli_mysqlnd.dll? Saya hanya punya php_mysqli.dlldi extfolder saya .
Pacerier
51

Jadi jika driver MySQL Native Driver (mysqlnd) tidak tersedia, dan oleh karena itu menggunakan bind_result dan fetch alih-alih get_result , kodenya menjadi:

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
sumber
$ stmt-> bind_result menghemat waktu saya. Ini adalah solusi yang bagus ketika get_result tidak tersedia.
Zafer
2
pertanyaan: dari mana variabel $ EmailVerfied berasal?
Rotimi
@ Akintunde007: $EmailVerfieddibuat dengan panggilan ke bind_result().
AbraCadaver
Mendapatkan error "Uncaught Error: Call to undefined method mysqli_stmt :: bind_results ()" dengan menggunakan kode
Devil's Dream
Jika saya memiliki query sql seperti "Select * from table_name" lalu bagaimana mendeklarasikan di dalam bind_result (). * operator
Inderjeet
46

Sistem Anda kehilangan driver mysqlnd!

Jika Anda dapat menginstal paket baru di server (berbasis Debian / Ubuntu), instal driver:

sudo apt-get install php5-mysqlnd

lalu mulai ulang server web Anda:

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

bagi mereka yang mencari alternatif untuk $result = $stmt->get_result()saya telah membuat fungsi ini yang memungkinkan Anda untuk meniru $result->fetch_assoc()tetapi menggunakan secara langsung objek 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;
}

seperti yang Anda lihat, ia membuat sebuah larik dan mengambilnya dengan data baris, karena ia menggunakan secara $stmt->fetch()internal, Anda dapat memanggilnya seperti yang Anda panggil mysqli_result::fetch_assoc(pastikan saja bahwa $stmtobjeknya terbuka dan hasilnya disimpan):

//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
sumber
Ini adalah jawaban pengganti drop-in termudah di sini. Bekerja dengan baik - terima kasih!
Alex Coleman
Menyelamatkan saya banyak waktu!
Jahaziel
3
Jika $statement->store_result();diperlukan sebelum memanggil fungsi, mengapa tidak memasukkannya saja ke dalam fungsi?
InsanityOnABun
Terima kasih. Baru saja menyelamatkan pantat saya pada tenggat waktu
Kolob Canyon
20

Dengan PHP versi 7.2 saya hanya menggunakan nd_mysqli daripada mysqli dan bekerja seperti yang diharapkan.

Langkah-langkah untuk mengaktifkannya ke server hosting GoDaddy-

  1. Login ke cpanel.
  2. Klik "Pilih versi PHP" .
  3. Seperti yang disediakan snapshot dari konfigurasi terbaru hapus centang "mysqli" dan aktifkan "nd_mysqli" .

masukkan deskripsi gambar di sini

IRSHAD
sumber
2
Terima kasih, saya jadi gila!
Ussaid Iqbal
1
Haaa, ini menghemat waktu saya! Terima kasih broh!
Nurul Huda
1
Bagus! jawaban sempurna untuk cPanel
Rashid
1
Terima kasih banyak!! Anda menyelamatkan saya, saya tidak bisa cukup berterima kasih
Enes Çalışkan
Jawaban ini harus di atas
Rishabh Gusain
10

Saya tahu ini sudah dijawab tentang masalah sebenarnya, namun saya ingin menawarkan solusi sederhana.

Saya ingin menggunakan metode get_results () namun saya tidak memiliki driver, dan saya tidak berada di suatu tempat untuk menambahkannya. Jadi, sebelum saya menelepon

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

Saya membuat array kosong, dan kemudian mengikat hasilnya sebagai kunci dalam array itu:

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

sehingga hasil tersebut dapat dengan mudah diteruskan ke metode atau dilemparkan ke objek untuk digunakan lebih lanjut.

Semoga ini membantu siapa saja yang ingin melakukan hal serupa.

Kirkland
sumber
7

Saya mendapatkan kesalahan yang sama di server saya - PHP 7.0 dengan ekstensi mysqlnd sudah diaktifkan.

Solusinya bagi saya (berkat halaman ini ) adalah membatalkan pilihan ekstensi mysqli dan memilih nd_mysqli sebagai gantinya.

NB - Anda mungkin dapat mengakses pemilih ekstensi di cPanel Anda. (Saya mengakses milik saya melalui opsi Pilih Versi PHP .)

larangan-geoengineering
sumber
Ini harus menjadi jawaban yang diterima. Jauh lebih baik untuk mengaktifkan ekstensi daripada mengedit seluruh skrip Anda untuk menggunakan metode lain! Oh dan itu berhasil untuk saya :)
ArabianMaiden
Saya memiliki masalah yang sama. Faktanya, menggunakan session_start()fungsi PHP membuat saya seperti nilai yang tidak ada. Kemudian saya meningkatkan ke versi 7.2PHP dan mengubah ekstensi mysqlimenjadi nd_mysqli (diperbaiki). Tapi, saya punya dua pertanyaan, apa perbedaan antara keduanya? dan apakah akan ada celah keamanan untuk menggunakan ekstensi itu?
jecorrales
6

Saya menyadari bahwa sudah lama tidak ada kegiatan baru tentang pertanyaan ini. Namun, seperti yang dikomentari oleh poster lain - get_result()sekarang hanya tersedia dalam PHP dengan menginstal driver asli MySQL (mysqlnd), dan dalam beberapa kasus, mungkin atau tidak diinginkan untuk menginstal mysqlnd. Jadi, saya pikir akan sangat membantu untuk memposting jawaban ini dengan info tentang bagaimana mendapatkan fungsionalitas yang get_result()menawarkan - tanpa menggunakan get_result().

get_result()is / sering dikombinasikan dengan fetch_array()to loop melalui kumpulan hasil dan menyimpan nilai dari setiap baris kumpulan hasil dalam array yang diindeks secara numerik atau array asosiatif. Misalnya, kode di bawah ini menggunakan get_result () dengan fetch_array () untuk mengulang melalui set hasil, menyimpan nilai dari setiap baris dalam array $ data [] yang diindeks secara numerik:

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

Namun, jika get_result()tidak tersedia (karena mysqlnd tidak diinstal), maka ini mengarah pada masalah bagaimana menyimpan nilai dari setiap baris hasil yang ditetapkan dalam sebuah array, tanpa menggunakan get_result(). Atau, bagaimana cara memigrasi kode lama yang digunakan get_result()untuk berjalan tanpanya (mis. Menggunakan bind_result()sebagai gantinya) - sambil sesedikit mungkin memengaruhi sisa kode.

Ternyata menyimpan nilai dari setiap baris dalam array yang diindeks secara numerik tidak begitu mudah digunakan bind_result(). bind_result()mengharapkan daftar variabel skalar (bukan array). Jadi, dibutuhkan beberapa upaya untuk membuatnya menyimpan nilai dari setiap baris hasil yang ditetapkan dalam sebuah array.

Tentu saja, kodenya dapat dengan mudah dimodifikasi sebagai berikut:

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

Tapi, ini mengharuskan kita untuk secara eksplisit mencantumkan $ data [0], $ data [1], dll. Secara individual dalam panggilan ke bind_result(), yang tidak ideal. Kami menginginkan solusi yang tidak mengharuskan kami harus secara eksplisit mencantumkan $ data [0], $ data [1], ... $ data [N-1] (di mana N adalah jumlah bidang dalam pernyataan pilih) dalam panggilan ke bind_results(). Jika kita memigrasi aplikasi lawas yang memiliki banyak query, dan setiap query mungkin berisi jumlah field yang berbeda dalam selectklausa, migrasi akan sangat padat karya dan rawan kesalahan jika kita menggunakan solusi seperti di atas .

Idealnya, kami menginginkan potongan kode 'drop-in replacement' - untuk mengganti hanya baris yang berisi get_result()fungsi dan while () loop di baris berikutnya. Kode pengganti harus memiliki fungsi yang sama dengan kode yang digantikannya, tanpa memengaruhi baris mana pun sebelumnya, atau baris apa pun setelahnya - termasuk baris di dalam perulangan while (). Idealnya, kami ingin kode pengganti menjadi sekadat mungkin, dan kami tidak ingin harus menyesuaikan kode pengganti berdasarkan jumlah kolom dalam selectklausa kueri.

Mencari di internet, saya menemukan sejumlah solusi yang digunakan bind_param()dengan call_user_func_array() (misalnya, secara dinamis mengikat parameter mysqli_stmt dan kemudian mengikat hasil (PHP) ), tetapi sebagian besar solusi yang saya temukan pada akhirnya mengarah pada hasil yang disimpan dalam array asosiatif, bukan array yang diindeks secara numerik, dan banyak dari solusi ini tidak sekompak seperti yang saya inginkan dan / atau tidak cocok sebagai 'pengganti drop-in'. Namun, dari contoh yang saya temukan, saya dapat menggabungkan solusi ini, yang sesuai dengan tagihan:

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

Tentu saja, perulangan for () bisa diciutkan menjadi satu baris agar lebih kompak.

Saya harap ini membantu siapa saja yang mencari solusi yang digunakan bind_result()untuk menyimpan nilai dari setiap baris dalam array yang diindeks secara numerik dan / atau mencari cara untuk memigrasi kode warisan menggunakan get_result(). Komentar diterima.

mti2935.dll
sumber
Yupp. Bergeser ke PDO 3 tahun yang lalu. Terima kasih.
Kumar Kush
5

Ini alternatif saya. Ini berorientasi objek dan lebih seperti 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();
    }
}

Pemakaian:

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

Saya telah menulis dua fungsi sederhana yang memberikan fungsionalitas yang sama $stmt->get_result();, tetapi mereka tidak memerlukan driver mysqlnd.

Anda cukup mengganti

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

dan

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

(Untuk mendapatkan jumlah baris yang dikembalikan, Anda dapat menggunakan $stmt->num_rows.)

Anda hanya perlu menempatkan dua fungsi ini yang telah saya tulis di suatu tempat di Script PHP Anda . (misalnya tepat di bawah)

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

Bagaimana cara kerjanya :

Kode saya menggunakan $stmt->result_metadata();fungsi untuk mengetahui berapa banyak dan bidang mana yang dikembalikan dan kemudian secara otomatis mengikat hasil yang diambil ke referensi yang dibuat sebelumnya. Bekerja seperti pesona!

Stefan S.
sumber
Tidak tahu mengapa itu tidak disukai. Ini bekerja dengan sangat baik - Saya telah menggunakannya di banyak proyek.
Stefan S.