Gọi đến phương thức không xác định mysqli_stmt :: get_result


113

Đây là mã của tôi:

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

Tôi gặp lỗi ở dòng cuối cùng là: Gọi đến phương thức không xác định mysqli_stmt :: get_result ()

Đây là mã cho 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();
        }
    }
}

Nếu tôi viết dòng này:

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

Nó in 'Tuyên bố KHÔNG chuẩn bị' . Nếu tôi chạy truy vấn trực tiếp trong IDE thay thế? đánh dấu bằng các giá trị, nó hoạt động tốt. Xin lưu ý rằng đối tượng $ conn hoạt động tốt trong các truy vấn khác trong dự án.

Mọi sự giúp đỡ xin vui lòng .......


Tôi nghĩ bạn đã quên $stmt = $conn->mysqli->stmt_init();?
favoretti vào

Vui lòng kiểm tra xem các biến này có $_POST['EmailID'], $_POST['SLA'], $_POST['Password']được gửi đúng cách hay không bằng cách sử dụng biểu mẫu HTML với phương thức POST
ajreal, 30/11/11

@ajreal: Các biến đang được đăng chính xác. Tôi đã thử nghiệm chúng bằng print_r ($ _ POST).
Kumar Kush

@favoretti: Tôi đã thử sử dụng $ stmt = $ conn-> mysqli-> stmt_init (); . Vẫn không có may mắn.
Kumar Kush

Một điều tôi muốn đề cập là tôi đã sử dụng mã tương tự là những nơi khác và chúng hoạt động tốt.
Kumar Kush

Câu trả lời:


146

Vui lòng đọc ghi chú người dùng cho phương pháp này:

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

Nó yêu cầu trình điều khiển mysqlnd ... nếu nó không được cài đặt trên không gian web của bạn, bạn sẽ phải làm việc với 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
Cảm ơn rất nhiều. Điều đó đã hiệu quả. Tôi đã bỏ ghi chú phần mở rộng = php_mysqli_mysqlnd.dll trong php.ini ; và khởi động lại các dịch vụ Apache2.2 và MySQL. Tôi có nên bỏ ghi chú phần mở rộng dòng = php_mysqli_libmysql.dll không? Theo một trang khác, mysqlnd nhanh hơn libmysql. Ngoài ra, tôi có thể mong đợi mysqlnd được cài đặt trên hầu hết các nhà cung cấp dịch vụ lưu trữ phổ biến không?
Kumar Kush

1
stmt_init () chỉ cần thiết cho một câu lệnh chuẩn bị theo thủ tục. vì vậy bạn không cần nó! Nhìn: liên kết Đối với libmysql : không biết. Và tôi sẽ không tin tưởng vào các nhà cung cấp dịch vụ lưu trữ cho việc cài đặt mysqlnd.dll ... tốt hơn hãy thử một số giải pháp thay thế!
bekay

2
Lưu ý: mysqli_stmt::get_result()chỉ có ở phiên bản PHP v5.3.0 trở lên.
Raptor

4
@bekay Bạn vừa cứu cho tôi một máy tính xách tay mới và một cửa sổ mới. Nếu +10 khả dụng, tôi sẽ cung cấp cho bạn
James Cushing

1
@ kush.impetus, Bạn tải xuống ở php_mysqli_mysqlnd.dllđâu? Tôi chỉ có php_mysqli.dlltrong extthư mục của tôi .
Pacerier

51

Vì vậy, nếu trình điều khiển MySQL Native Driver (mysqlnd) không có sẵn và do đó sử dụng bind_resulttìm nạp thay vì get_result , mã sẽ trở thành:

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 đã tiết kiệm thời gian của tôi. Đó là một giải pháp tuyệt vời khi get_result không có sẵn.
Zafer

2
câu hỏi: biến $ EmailVerfied đến từ đâu?
Rotimi

@ Akintunde007: $EmailVerfiedđược tạo bởi lệnh gọi tới bind_result().
AbraCadaver

Gặp lỗi "Lỗi chưa giải quyết được: Cuộc gọi đến phương thức không xác định mysqli_stmt :: bind_results ()" bằng cách sử dụng mã
Devil's Dream

Nếu tôi có truy vấn sql như "Chọn * từ tên_bảng" thì làm thế nào để khai báo bên trong bind_result (). * nhà điều hành
Inderjeet

46

Hệ thống của bạn thiếu trình điều khiển mysqlnd!

Nếu bạn có thể cài đặt các gói mới trên máy chủ (dựa trên Debian / Ubuntu), hãy cài đặt trình điều khiển:

sudo apt-get install php5-mysqlnd

và sau đó khởi động lại máy chủ web của bạn:

sudo /etc/init.d/apache2 restart

39

cho những người đang tìm kiếm một giải pháp thay thế cho $result = $stmt->get_result()tôi, tôi đã thực hiện chức năng này cho phép bạn bắt chước $result->fetch_assoc()nhưng sử dụng trực tiếp đối tượng 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;
}

như bạn có thể thấy, nó tạo một mảng và tìm nạp nó với dữ liệu hàng, vì nó sử dụng $stmt->fetch()nội bộ, bạn có thể gọi nó như cách bạn gọi mysqli_result::fetch_assoc(chỉ cần đảm bảo rằng $stmtđối tượng đang mở và kết quả được lưu trữ):

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

Đây là câu trả lời thay thế thả vào dễ nhất ở đây. Làm việc rất tốt - cảm ơn!
Alex Coleman

Đã tiết kiệm cho tôi rất nhiều thời gian!
Jahaziel

3
Nếu $statement->store_result();cần trước khi gọi hàm, tại sao không chỉ đưa nó vào hàm?
InsanityOnABun

Cảm ơn bạn. Chỉ cần lưu ass của tôi về thời hạn một
Kolob Canyon

20

Với phiên bản PHP 7.2, tôi chỉ sử dụng nd_mysqli thay vì mysqli và nó hoạt động như mong đợi.

Các bước để kích hoạt nó vào máy chủ lưu trữ Godaddy-

  1. Đăng nhập vào cpanel.
  2. Nhấp vào "Chọn phiên bản PHP" .
  3. Như đã cung cấp, ảnh chụp nhanh của các cấu hình mới nhất, hãy bỏ chọn "mysqli" và bật "nd_mysqli" .

nhập mô tả hình ảnh ở đây


2
Cảm ơn bạn, tôi đã phát điên!
Ussaid Iqbal

1
Haaa, điều này tiết kiệm thời gian của tôi! Cảm ơn anh!
Nurul Huda

1
tuyệt quá! câu trả lời hoàn hảo cho cPanel
Rashid

1
Cảm ơn bạn rất nhiều!! Bạn cứu tôi, tôi không thể cảm ơn bạn đủ
Enes Çalışkan

Câu trả lời này nên ở trên cùng
Rishabh Gusain

10

Tôi biết điều này đã được giải đáp về vấn đề thực tế là gì, tuy nhiên tôi muốn đưa ra một giải pháp đơn giản.

Tôi muốn sử dụng phương thức get_results () tuy nhiên, tôi không có trình điều khiển và tôi không có ở đâu để có thể bổ sung. Vì vậy, trước khi tôi gọi

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

Tôi đã tạo một mảng trống và sau đó chỉ ràng buộc các kết quả dưới dạng các khóa trong mảng đó:

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

để các kết quả đó có thể dễ dàng được chuyển vào các phương thức hoặc truyền sang một đối tượng để sử dụng tiếp.

Hy vọng điều này sẽ giúp bất kỳ ai đang muốn làm điều gì đó tương tự.


7

Tôi cũng gặp lỗi này trên máy chủ của mình - PHP 7.0 với mysqlnd phần mở rộng đã được bật.

Giải pháp dành cho tôi (nhờ trang này ) là bỏ chọn tiện ích mở rộng mysqli và chọn nd_mysqli thay thế.

NB - Bạn có thể truy cập bộ chọn tiện ích mở rộng trong cPanel của mình. (Tôi truy cập của tôi thông qua tùy chọn Chọn Phiên bản PHP .)


Đây phải là câu trả lời được chấp nhận. Bật tiện ích mở rộng tốt hơn nhiều so với việc chỉnh sửa toàn bộ tập lệnh của bạn để sử dụng phương pháp khác! Oh và nó làm việc cho tôi :)
ArabianMaiden

Tôi đã từng gặp vấn đề tương tự. Trên thực tế, việc sử dụng session_start()hàm của PHP khiến tôi giống như một giá trị không tồn tại. Sau đó, tôi đã nâng cấp lên phiên bản 7.2PHP và thay đổi phần mở rộng của mysqlithành nd_mysqli (cố định). Nhưng, tôi có hai câu hỏi, sự khác biệt giữa hai câu hỏi này là gì? và liệu có lỗ hổng nào về bảo mật khi sử dụng tiện ích mở rộng đó không?
jecorrales

6

Tôi nhận ra rằng đã lâu rồi không có bất kỳ hoạt động mới nào về câu hỏi này. Nhưng, như những người đăng khác đã nhận xét - get_result()hiện chỉ có sẵn trong PHP bằng cách cài đặt trình điều khiển gốc MySQL (mysqlnd) và trong một số trường hợp, có thể không thực hiện được hoặc không mong muốn cài đặt mysqlnd. Vì vậy, tôi nghĩ sẽ hữu ích nếu đăng câu trả lời này kèm theo thông tin về cách có được chức năng get_result()cung cấp - mà không cần sử dụng get_result().

get_result()is / thường được kết hợp với fetch_array()để lặp qua một tập kết quả và lưu trữ các giá trị từ mỗi hàng của tập kết quả trong một mảng được lập chỉ mục số hoặc kết hợp. Ví dụ: đoạn mã bên dưới sử dụng get_result () với fetch_array () để lặp qua một tập kết quả, lưu trữ các giá trị từ mỗi hàng trong mảng $ data [] được lập chỉ mục số:

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

Tuy nhiên, nếu get_result()không có sẵn (vì mysqlnd không được cài đặt), thì điều này dẫn đến vấn đề làm thế nào để lưu trữ các giá trị từ mỗi hàng của tập kết quả trong một mảng mà không cần sử dụng get_result(). Hoặc, cách di chuyển mã kế thừa sử dụng get_result()để chạy mà không có mã đó (ví dụ: sử dụng bind_result()thay thế) - trong khi tác động ít nhất có thể đến phần còn lại của mã.

Nó chỉ ra rằng việc lưu trữ các giá trị từ mỗi hàng trong một mảng được lập chỉ mục bằng số không dễ sử dụng bind_result(). bind_result()mong đợi một danh sách các biến vô hướng (không phải là một mảng). Vì vậy, phải làm một số việc để làm cho nó lưu trữ các giá trị từ mỗi hàng của tập kết quả trong một mảng.

Tất nhiên, mã có thể dễ dàng được sửa đổi như sau:

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

Tuy nhiên, điều này yêu cầu chúng tôi liệt kê rõ ràng $ data [0], $ data [1], v.v. trong lệnh gọi tới bind_result(), điều này không lý tưởng. Chúng tôi muốn một giải pháp không yêu cầu chúng tôi phải liệt kê rõ ràng $ data [0], $ data [1], ... $ data [N-1] (trong đó N là số trường trong câu lệnh select) trong cuộc gọi tới bind_results(). Nếu chúng tôi đang di chuyển một ứng dụng cũ có số lượng lớn các truy vấn và mỗi truy vấn có thể chứa một số trường khác nhau trongselect mệnh đề, thì việc di chuyển sẽ rất tốn công sức và dễ xảy ra lỗi nếu chúng ta sử dụng một giải pháp như trên .

Lý tưởng nhất, chúng tôi muốn một đoạn mã 'thay thế thả vào' - để chỉ thay thế dòng chứa get_result()hàm và vòng lặp while () trên dòng tiếp theo. Mã thay thế phải có cùng chức năng với mã mà nó đang thay thế, mà không ảnh hưởng đến bất kỳ dòng nào trước hoặc bất kỳ dòng nào sau đó - kể cả các dòng bên trong vòng lặp while (). Lý tưởng nhất là chúng tôi muốn mã thay thế càng nhỏ gọn càng tốt và chúng tôi không muốn phải xử lý mã thay thế dựa trên số lượng trường trong selectmệnh đề của truy vấn.

Tìm kiếm trên internet, tôi đã tìm thấy một số giải pháp sử dụng bind_param()với call_user_func_array() (ví dụ: Liên kết động các tham số mysqli_stmt và sau đó liên kết kết quả (PHP) ), nhưng hầu hết các giải pháp mà tôi tìm thấy cuối cùng đều dẫn đến kết quả được lưu trữ trong một mảng liên kết, không một mảng được lập chỉ mục bằng số và nhiều giải pháp trong số này không nhỏ gọn như tôi muốn và / hoặc không phù hợp như 'các giải pháp thay thế thả vào'. Tuy nhiên, từ các ví dụ mà tôi tìm thấy, tôi đã có thể đúc kết lại giải pháp này, phù hợp với hóa đơn:

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

Tất nhiên, vòng lặp for () có thể được thu gọn thành một dòng để làm cho nó gọn gàng hơn.

Tôi hy vọng điều này sẽ giúp ích cho bất kỳ ai đang tìm kiếm giải pháp sử dụng bind_result()để lưu trữ các giá trị từ mỗi hàng trong một mảng được lập chỉ mục số và / hoặc đang tìm cách di chuyển mã kế thừa bằng cách sử dụng get_result(). Bình luận được chào đón.


Yupp. Chuyển sang PDO 3 năm trước. Dù sao đi nữa cũng xin cám ơn.
Kumar Kush

5

Đây là giải pháp thay thế của tôi. Nó hướng đối tượng và giống với những thứ mysql / mysqli hơn.

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

Sử dụng:

$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

Tôi đã viết hai hàm đơn giản có cùng chức năng $stmt->get_result();nhưng chúng không yêu cầu trình điều khiển mysqlnd.

Bạn chỉ cần thay thế

$result = $stmt->get_result(); với $fields = bindAll($stmt);

$row= $stmt->get_result(); với $row = fetchRowAssoc($stmt, $fields); .

(Để lấy số hàng trả về bạn có thể sử dụng $stmt->num_rows.)

Bạn chỉ cần đặt hai hàm này mà tôi đã viết ở đâu đó trong PHP Script của bạn . (ví dụ ngay dưới cùng)

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

Cách thức hoạt động :

Mã của tôi sử dụng $stmt->result_metadata();hàm để tìm ra số lượng và trường nào được trả về và sau đó tự động liên kết các kết quả được tìm nạp với các tham chiếu được tạo trước. Hoạt động như một sự quyến rũ!


Không biết tại sao nó bị bỏ phiếu. Nó hoạt động rất tốt - tôi đã sử dụng nó trong nhiều dự án.
Stefan S.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.