mysqli_stmt::get_result

mysqli_stmt_get_result

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

mysqli_stmt::get_result -- mysqli_stmt_get_result将准备好的语句的结果集作为 mysqli_result 对象获取

描述

面向对象风格

public mysqli_stmt::get_result(): mysqli_result|false

过程式风格

mysqli_stmt_get_result(mysqli_stmt $statement): mysqli_result|false

将准备好的语句的结果集作为 mysqli_result 对象获取。数据将从 MySQL 服务器提取到 PHP。此方法应该只用于产生结果集的查询。

注意:

仅适用于 mysqlnd.

注意:

此函数不能与 mysqli_stmt_store_result() 一起使用。这两个函数都从 MySQL 服务器检索完整的结果集。

参数

statement

仅过程式风格:由 mysqli_stmt_init() 返回的 mysqli_stmt 对象。

返回值

失败时返回 false。对于成功产生结果集的查询,例如 SELECT, SHOW, DESCRIBEEXPLAINmysqli_stmt_get_result() 将返回一个 mysqli_result 对象。对于其他成功的查询,mysqli_stmt_get_result() 将返回 falsemysqli_stmt_errno() 函数可用于区分 false 的两种原因;由于错误,在 PHP 7.4.13 之前,必须使用 mysqli_errno() 来实现此目的。

错误/异常

如果启用了 mysqli 错误报告 (MYSQLI_REPORT_ERROR) 并且请求的操作失败,则会生成警告。如果此外模式设置为 MYSQLI_REPORT_STRICT,则会抛出 mysqli_sql_exception 而不是警告。

示例

示例 #1 面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

$query = "SELECT Name, Population, Continent FROM Country WHERE Continent=? ORDER BY Name LIMIT 1";

$stmt = $mysqli->prepare($query);
$stmt->bind_param("s", $continent);

$continentList = array('Europe', 'Africa', 'Asia', 'North America');

foreach (
$continentList as $continent) {
$stmt->execute();
$result = $stmt->get_result();
while (
$row = $result->fetch_array(MYSQLI_NUM)) {
foreach (
$row as $r) {
print
"$r ";
}
print
"\n";
}
}

示例 #2 过程式风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect("localhost", "my_user", "my_password", "world");

$query = "SELECT Name, Population, Continent FROM Country WHERE Continent=? ORDER BY Name LIMIT 1";

$stmt = mysqli_prepare($link, $query);
mysqli_stmt_bind_param($stmt, "s", $continent);

$continentList= array('Europe', 'Africa', 'Asia', 'North America');

foreach (
$continentList as $continent) {
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while (
$row = mysqli_fetch_array($result, MYSQLI_NUM)) {
foreach (
$row as $r) {
print
"$r ";
}
print
"\n";
}
}

以上示例将输出类似于以下内容

Albania 3401200 Europe 
Algeria 31471000 Africa 
Afghanistan 22720000 Asia 
Anguilla 8000 North America

参见

添加注释

用户贡献的注释 6 个注释

匿名
10 年前
我在一台没有安装 mysqlnd 的服务器上遇到了很多麻烦,并且有很多头痛的问题。

如果您没有安装/加载 mysqlnd,无论如何,尝试调用 "mysqli_stmt_get_result()" 时会得到一个未定义的引用。

我编写了自己的 mysqli_stmt_get_result() 和 mysqli_result_fetch_array() 来配合使用。

<?php
class iimysqli_result
{
public
$stmt, $nCols;
}

function
iimysqli_stmt_get_result($stmt)
{
/** 解释:
* 我们正在创建一个假的“结果”结构,使我们能够
* 通过 mysqli_query() 执行的查询获得源代码级别的等效语法。
*
* $stmt = mysqli_prepare($conn, "");
* mysqli_bind_param($stmt, "types", ...);
*
* $param1 = 0;
* $param2 = 'foo';
* $param3 = 'bar';
* mysqli_execute($stmt);
* $result _mysqli_stmt_get_result($stmt);
* [ $arr = _mysqli_result_fetch_array($result);
* || $assoc = _mysqli_result_fetch_assoc($result); ]
* mysqli_stmt_close($stmt);
* mysqli_close($conn);
*
* 在源代码级别,此方法与 mysqlnd 没有区别。
**/
$metadata = mysqli_stmt_result_metadata($stmt);
$ret = new iimysqli_result;
if (!
$ret) return NULL;

$ret->nCols = mysqli_num_fields($metadata);
$ret->stmt = $stmt;

mysqli_free_result($metadata);
return
$ret;
}

function
iimysqli_result_fetch_array(&$result)
{
$ret = array();
$code = "return mysqli_stmt_bind_result(\$result->stmt ";

for (
$i=0; $i<$result->nCols; $i++)
{
$ret[$i] = NULL;
$code .= ", \$ret['" .$i ."']";
};

$code .= ");";
if (!eval(
$code)) { return NULL; };

// 这应该会推进 "$stmt" 游标。
if (!mysqli_stmt_fetch($result->stmt)) { return NULL; };

// 返回我们构建的数组。
return $ret;
}
?>

希望这能帮到一些人。
匿名
6 年前
求求你了。
我一直试图从这个函数中获取结果集,但我完全没有成功,花了将近 3 个小时!

如果你正在使用 mysqli_stmt_get_results() 来获取结果集,并且同时使用 mysqli_stmt_store_results 来检索返回的行数,那你将会遇到很大的麻烦!

PHP 文档说明,要检索由准备好的 select sql 语句返回的行数,应该分别调用以下语句:

mysqli_stmt_execute($stmt);
mysqli_stmt_store_result($stmt);
$num_rows = mysqli_stmt_num_rows($stmt);

如果你同时使用 mysqli_stmt_get_result(),这将会是一个巨大的死亡陷阱!!这样做会导致不同的结果,具体取决于你首先调用哪个语句,但最终你将不会得到想要的结果。

总之,请,请不要同时使用 mysqli_stmt_store_result() 和 mysqli_stmt_get_result()。这将会是一个巨大的死亡陷阱。

解决方案
如果你正在尝试获取结果集,并且需要同时获取返回的行数,请分别使用以下语句:

$result_set = mysqli_stmt_get_results($stmt);
$num_rows = mysqli_num_rows($result_set);

反思自己的行为,这个解决方案可能看起来相当明显。但是,对于像我这样使用 PHP 的新手,或者对预处理语句不太熟悉的人来说,很容易在使用谷歌和自学时迷失方向。

总结
千万不要同时使用 mysqli_stmt_store_result($stmt) 和 mysqli_stmt_num_rows($stmt) 以及 mysqli_stmt_get_result($stmt)。你会后悔的!!我已经在这个问题上卡了几个小时了,谷歌没有给我任何答案!
[email protected]
6 年前
为了防止其他人花几个小时尖叫着试图弄清楚为什么当你启用了原生驱动程序时它不起作用,这是因为你需要确保在你的服务器上同时启用原生驱动程序 mysqlnd 和 nd_mysqli,如果你想使用此功能。

否则,只启用 mysqlnd 原生驱动程序不包括 mysqli_stmt_get_result 函数,因为该函数显然位于 nd_mysqli 原生驱动程序中。不幸的是,大多数文档只谈论 mysqlnd 原生驱动程序。

一旦你同时启用了这两个原生驱动程序,该函数就能按文档说明的那样工作。
[email protected]
12 年前
请注意,此方法需要 mysqlnd 驱动程序。否则,你会得到这个错误:Call to undefined method mysqli_stmt::get_result()
Haravikk
7 年前
对于那些感兴趣的人来说,这个函数似乎总是产生一个存储的结果,使其等效于 mysqli::store_result(),而不是像 mysqli::use_result() 那样按需获取。

这很重要,因为它意味着你无法像通常那样通过在获取之前调用 mysqli_stmt::store_result() 来控制结果的性质,正如我个人所期望的那样。

因此,如果你想模拟 mysqli::use_result() 的行为,你仍然需要使用 mysqli_stmt::bind_param() 和 mysqli_stmt::fetch()。
HeadlessDev
5 年前
感谢所有留下笔记的人,没有他们,我无法完成我的工作。我编写了这个函数,并参考了本页和其他页面的笔记。

我没有使用 mysqlnd,但想要能够将查询的 get_result() 作为对象获取。

请注意:我不是 PHP 专家

以下是如何使用我的 get_result() 登录用户的示例
<?php
// 使用此函数之前,请先对输入进行清理
function login($email, $password){
require
'connect_db.php';
$query = $sql->stmt_init();
if(
$query->prepare("SELECT CustomerId, Password, Admin FROM users WHERE Email = ?")){
$query->bind_param("s",$email);
$result = get_result($query); // 在这里使用函数
if($result != NULL){
$user = $result[0];
if(
password_verify($password, $user->Password)){
$_SESSION['user_id'] = $user->CustomerId;
if(
$user->Admin == 1){
$_SESSION['admin'] = true;
}
$sql->close();
return
true;
}
}
}
$sql->close();
// 如果到达这里,则表示用户未登录
return false;
}

// 返回一个数组,其中每一行都是一个对象
function get_result($stmt){
$stmt->execute(); // 执行查询
$stmt->store_result(); // 存储结果
$num_rows = $stmt->num_rows; // 获取结果数量
$results = NULL;
if(
$num_rows > 0){
// 获取有关结果的元数据
$meta = $stmt->result_metadata();
// 在这里获取所有列/字段名称并创建绑定代码
$bind_code = "return mysqli_stmt_bind_result(\$stmt, ";
while(
$_field = $meta->fetch_field()){
$bind_code .= "\$row[\"".$_field->name."\"], ";
}
// 将尾部的 ", " 替换为 ");"
$bind_code = substr_replace($bind_code,");", -2);
// 运行代码,如果运行失败,则返回 NULL
if(!eval($bind_code)) {
$stmt->close();
return
NULL;
}
// 这是我们创建对象并将其添加到最终结果数组中的地方
for($i=0;$i<$num_rows;$i++){
// 通过索引获取行
$stmt->data_seek($i);
// 使用新行值更新绑定变量(在 $bind_code 中使用)
$stmt->fetch();
foreach(
$row as $key=>$value){
// 使用列/字段名称作为索引创建数组
$_result[$key] = $value;
}
// 将 $_result 转换为对象并附加到最终结果中
$results[$i] = (object)$_result;
}
}
$stmt->close();
return
$results;
}
?>
To Top