调用未定义的方法 mysqli_stmt::get_result

Call to undefined method mysqli_stmt::get_result

提问人:Kumar Kush 提问时间:11/30/2011 最后编辑:Kumar Kush 更新时间:12/8/2022 访问量:154423

问:

这是我的代码:

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对象在项目中的其他查询中工作正常。

请帮忙.......

php mysqli

评论

0赞 favoretti 11/30/2011
我想你忘了?$stmt = $conn->mysqli->stmt_init();
0赞 ajreal 11/30/2011
请检查这些变量是否使用带有 POST 方法的 HTML 表单正确提交$_POST['EmailID'], $_POST['SLA'], $_POST['Password']
0赞 Kumar Kush 11/30/2011
@ajreal:变量已正确发布。我使用 print_r($_POST)测试了它们。
0赞 Kumar Kush 11/30/2011
@favoretti:我尝试使用$stmt = $conn->mysqli->stmt_init();。还是没有运气。
0赞 Kumar Kush 11/30/2011
我想提的一件事是,我在其他地方使用了类似的代码,它们工作正常。

答:

160赞 bekay 12/1/2011 #1

请阅读此方法的用户说明:

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

它需要 mysqlnd 驱动程序...如果它没有安装在你的网站空间上,你将不得不使用 bind_result() 和 fetch()

评论

5赞 Kumar Kush 12/2/2011
多谢。这奏效了。我在php.ini中取消了extension=php_mysqli_mysqlnd.dll的注释;并重新启动了 Apache2.2 和 MySQL 服务。我应该取消注释行 extension=php_mysqli_libmysql.dll吗?根据另一页,mysqlnd 比 libmysql 快。另外,我可以期望在大多数流行的托管服务提供商上安装mysqlnd吗?
1赞 bekay 12/2/2011
stmt_init() 仅用于程序性准备语句。所以你不需要它!看:link 至于libmysql:不知道。而且我不会指望托管服务提供商安装 mysqlnd.dll ...最好尝试一些解决方法!
2赞 Raptor 11/28/2012
注意:仅适用于 PHP v5.3.0 或更高版本。mysqli_stmt::get_result()
4赞 James Cushing 4/24/2014
@bekay 你刚刚为我保存了一台新笔记本电脑和一个新窗口。如果+10可用,我会给你
1赞 Pacerier 6/29/2015
@kush.impetus,你在哪里下载?我只会在我的文件夹中。php_mysqli_mysqlnd.dllphp_mysqli.dllext
57赞 Bert Regelink 6/21/2012 #2

因此,如果 MySQL Native Driver (mysqlnd) 驱动程序不可用,因此使用 bind_resultfetch 而不是 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();
$stmt->bind_result($EmailVerified, $Blocked);
while ($stmt->fetch())
{
   /* Use $EmailVerified and $Blocked */
}
$stmt->close();
$conn->mysqli->close();
48赞 M_R_K 8/4/2013 #3

您的系统缺少 mysqlnd 驱动程序!

如果您能够在(基于 Debian/Ubuntu)服务器上安装新软件包,请安装驱动程序:

sudo apt-get install php5-mysqlnd

然后重新启动 Web 服务器:

sudo /etc/init.d/apache2 restart
10赞 Kirkland 12/13/2013 #4

我知道这已经回答了实际问题是什么,但是我想提供一个简单的解决方法。

我想使用 get_results() 方法,但是我没有驱动程序,而且我不在可以添加它的地方。所以,在我打电话之前

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

我创建了一个空数组,然后将结果绑定为该数组中的键:

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

这样,这些结果就可以很容易地传递到方法中或强制转换为对象以供进一步使用。

希望这对任何想做类似事情的人有所帮助。

42赞 MasterKitano 2/20/2015 #5

对于那些寻找替代方案的人,我制作了这个函数,它允许您模仿但直接使用 stmt 对象:$result = $stmt->get_result()$result->fetch_assoc()

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
$stmt = $mysqli_connection->prepare($query);
$stmt->execute();
$stmt->store_result();

while($assoc_array = fetchAssocStatement($stmt))
{
    //do your magic
}

评论

5赞 InsanityOnABun 8/19/2016
如果在调用函数之前需要,为什么不直接将其包含在函数中呢?$statement->store_result();
6赞 ch271828n 8/25/2015 #6

这是我的选择。它是面向对象的,更像是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
6赞 mti2935 7/15/2016 #7

我意识到已经有一段时间没有关于这个问题的任何新活动了。但是,正如其他发帖者所评论的那样 - 现在只能通过安装 MySQL 本机驱动程序 (mysqlnd) 在 PHP 中使用,并且在某些情况下,安装 mysqlnd 可能是不可能的或不可取的。因此,我认为发布此答案并提供有关如何获取所提供功能的信息会很有帮助 - 而不使用 .get_result()get_result()get_result()

get_result()is/was 通常与 循环遍历结果集,并将结果集每一行的值存储在数字索引或关联数组中。例如,下面的代码使用 get_result() 和 fetch_array() 遍历结果集,将每行的值存储在数字索引的 $data[] 数组中:fetch_array()

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

但是,如果不可用(因为未安装 mysqlnd),则会导致如何在不使用 .或者,如何迁移过去在没有它的情况下运行的遗留代码(例如,改用) - 同时尽可能减少对其余代码的影响。get_result()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"; 
}

但是,这要求我们在调用 时单独列出 $data[0]、$data[1] 等,这并不理想。我们想要一个解决方案,它不需要在调用 时显式列出 $data[0]、$data[1]、... $data[N-1](其中 N 是 select 语句中的字段数)。如果我们要迁移具有大量查询的旧应用程序,并且每个查询在子句中可能包含不同数量的字段,则迁移将非常耗费人力,并且如果我们使用上述解决方案,则容易出错。bind_result()bind_results()select

理想情况下,我们想要一段“插入式替换”代码 - 只替换包含函数的行和下一行的 while() 循环。替换代码应具有与它所替换的代码相同的功能,而不会影响之前的任何行或之后的任何行 - 包括 while() 循环中的行。理想情况下,我们希望替换代码尽可能紧凑,并且我们不希望必须根据查询子句中的字段数来修改替换代码。get_result()select

在互联网上搜索时,我发现许多使用 with 的解决方案(例如,动态绑定mysqli_stmt参数,然后绑定结果 (PHP)),但我找到的大多数解决方案最终导致结果存储在关联数组中,而不是数字索引数组中,并且其中许多解决方案并不像我想要的那么紧凑和/或不适合作为“直接替换”。但是,从我发现的示例中,我能够拼凑出这个符合要求的解决方案:bind_param()call_user_func_array()

$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() 循环可以折叠成一行以使其更紧凑。

我希望这可以帮助任何正在寻找解决方案的人,他们使用将每行的值存储在数字索引数组中和/或寻找一种使用 .欢迎评论。bind_result()get_result()

评论

0赞 Kumar Kush 9/29/2016
是的。3年前转向PDO。谢谢任何方式。
4赞 Stefan S. 2/21/2018 #8

我编写了两个简单的函数,它们提供了与 相同的功能,但它们不需要 mysqlnd 驱动程序。$stmt->get_result();

您只需

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

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

(要获取返回的行数,可以使用 。$stmt->num_rows

你只需要把我写的这两个函数放在你的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();

10赞 ban-geoengineering 7/6/2018 #9

我在我的服务器上遇到了同样的错误 - PHP 7.0 已经启用了 mysqlnd 扩展。

对我来说,解决方案(感谢此页面)是取消选择mysqli扩展并选择nd_mysqli

注意 - 您可以在cPanel中访问扩展选择器。(我通过“选择PHP版本”选项访问我的。

评论

0赞 androsfat 1/23/2023
我在共享托管上遇到了同样的问题,我只是禁用了扩展并启用了。mysqlind_mysqli
62赞 IRSHAD 10/24/2018 #10

在 PHP 7.2 版中,我只是使用 nd_mysqli 而不是 mysqli,它按预期工作。

将其启用到godaddy托管服务器的步骤-

  1. 登录到 cpanel。
  2. 点击“选择PHP版本”。
  3. 如提供,最新配置的快照取消选中“mysqli”并启用“nd_mysqli”。

enter image description here