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

时间:2011-11-30 04:20:42

标签: php mysqli

这是我的代码:

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

打印'声明未准备好'。如果我直接在IDE中运行查询替换?用值标记,它工作正常。请注意,$ conn对象在项目中的其他查询中工作正常。

请帮助.......

10 个答案:

答案 0 :(得分:141)

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

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

它需要mysqlnd驱动程序......如果它没有安装在您的网站空间上,您将需要使用BIND_RESULT& FETCH!

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

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

答案 1 :(得分:43)

因此,如果MySQL本机驱动程序(mysqlnd)驱动程序不可用,因此使用 bind_result 获取而不是 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();

答案 2 :(得分:42)

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

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

sudo apt-get install php5-mysqlnd

然后重新启动您的网络服务器:

sudo /etc/init.d/apache2 restart

答案 3 :(得分:35)

对于那些搜索$ result = stmt-> get_result()的替代品的人我已经创建了这个函数,它允许你模仿$ result-> fetch_assoc()但是直接使用stmt对象: / p>

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

希望这会有所帮助。

答案 4 :(得分:10)

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

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

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

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

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

这样可以很容易地将这些结果传递给方法或转换为对象以供进一步使用。

希望这有助于任何想要做类似事情的人。

答案 5 :(得分:7)

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

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

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

enter image description here

答案 6 :(得分:6)

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

get_result()经常与fetch_array()组合以循环遍历结果集,并将结果集的每一行中的值存储在数字索引或关联数组中。例如,下面的代码使用带有fetch_array()的get_result()循环遍历结果集,存储数字索引的$ 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),那么这会导致如何在数组中存储结果集的每一行的值,而不使用{{1 }}。或者,如何迁移使用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()子句中包含不同数量的字段,那么迁移将非常耗费人力并且如果我们容易出错则使用类似上面的解决方案。

理想情况下,我们需要一个“直接替换”的片段&#39;代码 - 仅替换下一行包含select函数和while()循环的行。替换代码应该具有与它替换的代码相同的功能,而不会影响之前的任何行,或者之后的任何行 - 包括while()循环内的行。理想情况下,我们希望替换代码尽可能紧凑,并且我们不希望根据查询的get_result()子句中的字段数来替换替换代码。

在互联网上搜索,我找到了许多使用selectbind_param()的解决方案 (例如,Dynamically bind mysqli_stmt parameters and then bind result (PHP)),但我发现的大多数解决方案最终导致结果存储在关联数组中,而不是数字索引数组,并且许多解决方案并不像我希望的那样紧凑/或不适合作为替代品&#39;。但是,从我发现的例子中,我能够拼凑出这个适合账单的解决方案:

call_user_func_array()

当然,for()循环可以折叠成一行,使其更紧凑。

我希望这可以帮助任何正在寻找使用$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"; } 的解决方案的人来存储数字索引数组中每行的值和/或寻找使用bind_result()迁移旧代码的方法。欢迎评论。

答案 7 :(得分:6)

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

对我来说,解决方案(感谢this page)是取消选择 mysqli 扩展名,然后选择 nd_mysqli

NB-您也许可以访问cPanel中的扩展程序选择器。 (我通过选择PHP版本选项访问我的。)

答案 8 :(得分:2)

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

您只需替换

$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();函数来确定返回了多少和哪些字段,然后自动将获取的结果绑定到预先创建的引用。像魅力一样工作!

答案 9 :(得分:0)

免责声明

<块引用>

不鼓励采用以下方法,它会大大降低代码可读性并可能导致变量冲突。如果您有 mysqlnd 驱动程序,那么请务必使用 get_result

如果您想将 * 通配符与 bind_result 一起使用而不必担心自己分配变量,这里是我想出的一个解决方案,它可以在运行时为您完成。

// Get column names 
$sql = 'SHOW COLUMNS FROM users';
$get_coulmns = $mysqli->query($sql);

while($row = $get_coulmns->fetch_assoc()){
    $columns[] = $row['Field'];
}

// Assign references
$variables = array();
for ($i = 0; $i < count($columns); $i++) {
    $variables[] = &${$columns[$i]};
}
 
/*
  Other code here
*/

// Unpack variable references
$stmt->bind_result(...$variables);

现在您可以自由使用数据库中定义的变量名称

echo $id, PHP_EOL;
echo $username, PHP_EOL;
echo $password, PHP_EOL;

... etc