在之前的文章中,我们就已经接触过 MYSQLI_result 相关的内容。它的作用其实就是一个查询的结果集。不过在 PDO 中,一般直接通过 query() 或者 PDOStatement 对象进行查询之后就会返回结果。但在 MySQLi 中,会把查询到的结果也放入一个对象中,这就是 MySQLI_result 对象。

MySQLI_result 对象属性

首先,我们要通过一段查询来获得一个 MySQLI_result 对象。

$stmt = $mysqli->prepare("select * from zyblog_test_user where username = 'kkk'");

$stmt->execute(); // 执行语句
$result = $stmt->get_result();
var_dump($result);
// object(mysqli_result)#3 (5) {
// ["current_field"]=>
// int(0)
// ["field_count"]=>
// int(4)
// ["lengths"]=>
// NULL
// ["num_rows"]=>
// int(7)
// ["type"]=>
// int(0)
// }

如果使用的 MYSQLI_STMT 的话,直接在 execute() 方法执行查询语句之后,就可以通过 get_result() 方法获得一个 MySQLI_result 对象。

在这个对象中,我们可以看到有 current_field 当前字段 、 field_count 字段数量 、 lengths 字段长度 、 num_rows 行数 、 type 这些属性内容。不少同学会发现,current_field 和 lengths 好像并没有什么实际的内容,其实这两个属性是需要在特定操作下才会显示内容的,比如 lengths 是要在 fetch() 结果集之后才会有信息的。

$result->fetch_array();
var_dump($result);
// ……
// ……
// ["lengths"]=>
// array(4) {
// [0]=>
// int(0)
// [1]=>
// int(3)
// [2]=>
// int(3)
// [3]=>
// int(2)
// }
// ……
// ……

而 current_field 属性的内容我们将在下面遍历查看字段信息的时候再展示它的内容。

查询结果集获取

MySQLI_result 对象的可见属性中,我们只能看到上面的那些信息。对于我们的业务开发来说其实用处不大,除了 num_rows 可以用来根据行数判断查询是否有结果之外,更重要的是我们要获取到结果集中的数据信息,这时就需要使用其它的函数来进行数据的获取了。

获取全部结果集

var_dump($result->fetch_all());
// array(7) {
// [0]=>
// array(4) {
// [0]=>
// int(42)
// [1]=>
// string(3) "kkk"
// [2]=>
// string(3) "666"
// [3]=>
// string(2) "k6"
// }
// ……
// …… $result->data_seek(0);
var_dump($result->fetch_all(MYSQLI_ASSOC));
// array(7) {
// [0]=>
// array(4) {
// ["id"]=>
// int(42)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }
// ……
// ……

fetch_all() 方法就是用来获取全部的数据集内的数据,并以数组的形式返回,它可以指定返回的格式,默认情况下是 MYSQLI_NUM 这种数组下标的形式,和 PDO 类似,我们直接指定为 MySQLI_ASSOC 就可以返回键名形式的数据内容。

data_seek() 方法是移动结果集的下标。当我们获取或者使用后面要介绍的方法循环遍历完成一次结果集之后,再次遍历的话它的游标已经处于最后一位的,这样是无法获取数据的。在上面的代码中,我们就是将游标两次返回到 0 下标的位置,也就是最初始的位置,这样我们就可以重复地操作这一个结果集了。

获取普通结果集

如果要一行一行数据的获取,我们就可以使用各种形式的结果集数据获取方式。

var_dump($result->fetch_array());
// array(8) {
// [0]=>
// int(42)
// ["id"]=>
// int(42)
// [1]=>
// string(3) "kkk"
// ["username"]=>
// string(3) "kkk"
// [2]=>
// string(3) "666"
// ["password"]=>
// string(3) "666"
// [3]=>
// string(2) "k6"
// ["salt"]=>
// string(2) "k6"
// } var_dump($result->fetch_array(MYSQLI_ASSOC));
// array(4) {
// ["id"]=>
// int(43)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }

使用 fetch_array() 就是获取下一行的结果数据并以数组的形式返回,同样它也可以指定返回结果集的格式,和 fetch_all() 是类似的,只不过它是只获取下一行而不是全部的数据集,而且它的参数默认是返回的 MYSQLI_BOTH ,也就是数字下标和键名下标同时返回结果。

另外还有一个 fetch_assoc() 方法,直接就是返回 MYSQLI_ASSOC 格式的数据,这个方法不需要任何参数,它可以看成是 fetch_array(MYSQLI_ASSOC) 这种使用方式的一个封装。

var_dump($result->fetch_assoc());
// array(4) {
// ["id"]=>
// int(42)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }

而另外一个方法 fetch_row() ,则可以看成是和 fetch_array(MYSQLI_NUM) 相似的一个方法。它其实就是默认指定为 MySQLI_NUM 的结构返回方式。

var_dump($result->fetch_row());
// array(4) {
// [0]=>
// int(43)
// [1]=>
// string(3) "kkk"
// [2]=>
// string(3) "666"
// [3]=>
// string(2) "k6"
// }

获取对象结果集

获取对象结果集其实和 PDO 中的相关功能也是类似的,它就是将结果直接放到一个类中,并实例化返回一个对象。

ar_dump($result->fetch_object());
// object(stdClass)#4 (4) {
// ["id"]=>
// int(42)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }

在这里我们没有指定类,所以它使用的是 stdClass 来返回的对象结构。我们也可以指定一个类,并且可以为这个类的构造函数传递参数,这一点也和 PDO 中的相关功能一样。

class User
{
public function __construct()
{
print_r(func_get_args());
}
}
var_dump($result->fetch_object('User', [1, 2, 3]));
// Array
// (
// [0] => 1
// [1] => 2
// [2] => 3
// )
// object(User)#4 (4) {
// ["id"]=>
// int(42)
// ["username"]=>
// string(3) "kkk"
// ["password"]=>
// string(3) "666"
// ["salt"]=>
// string(2) "k6"
// }

查询结果集字段信息获取

接下来我们再看看 MySQLI_result 对象中的字段相关信息的获取。我们可以直接获取到当前查询的结果集中的所有字段信息。

while ($finfo = $result->fetch_field()) {
var_dump($result->current_field);
var_dump($finfo);
}
// int(1)
// object(stdClass)#4 (13) {
// ["name"]=>
// string(2) "id"
// ["orgname"]=>
// string(2) "id"
// ["table"]=>
// string(16) "zyblog_test_user"
// ["orgtable"]=>
// string(16) "zyblog_test_user"
// ["def"]=>
// string(0) ""
// ["db"]=>
// string(9) "blog_test"
// ["catalog"]=>
// string(3) "def"
// ["max_length"]=>
// int(0)
// ["length"]=>
// int(11)
// ["charsetnr"]=>
// int(63)
// ["flags"]=>
// int(49667)
// ["type"]=>
// int(3)
// ["decimals"]=>
// int(0)
// }
// int(2)
// object(stdClass)#5 (13) {
// ["name"]=>
// string(8) "username"
// ["orgname"]=>
// string(8) "username"
// ……
// ……

在这段代码中,我们查看了 MySQLI_result 对象的 current_field 属性信息,可以看出,它指出的就是当前位于哪个字段的下标。

字段的信息非常详细,这些属性的键名也很直观,这里就不作详细的说明了。

$result->field_seek(1);
while ($finfo = $result->fetch_field()) {
var_dump($finfo);
}
// object(stdClass)#5 (13) {
// ["name"]=>
// string(8) "username"
// ["orgname"]=>
// string(8) "username"

我们同样也可以通过 field_seek() 方法来移动字段遍历的游标。在这里我们将游标移动到 1 ,就会从第二个 username 字段开始遍历。

var_dump($result->fetch_fields());
// array(4) {
// [0]=>
// object(stdClass)#5 (13) {
// ["name"]=>
// string(2) "id"
// ["orgname"]=>
// string(2) "id"
// ["table"]=>
// string(16) "zyblog_test_user"
// ["orgtable"]=>
// string(16) "zyblog_test_user"
// ["def"]=>
// string(0) ""
// ["db"]=>
// string(9) "blog_test"
// ["catalog"]=>
// string(3) "def"
// ["max_length"]=>
// int(0)
// ["length"]=>
// int(11)
// ["charsetnr"]=>
// int(63)
// ["flags"]=>
// int(49667)
// ["type"]=>
// int(3)
// ["decimals"]=>
// int(0)
// }
// [1]=>
// object(stdClass)#4 (13) {
// ["name"]=>
// string(8) "username" var_dump($result->fetch_field_direct(2));
// object(stdClass)#7 (13) {
// ["name"]=>
// string(8) "password"
// ["orgname"]=>
// string(8) "password"
// ["table"]=>
// string(16) "zyblog_test_user"
// ["orgtable"]=>
// string(16) "zyblog_test_user"
// ["def"]=>
// string(0) ""
// ["db"]=>
// string(9) "blog_test"
// ["catalog"]=>
// string(3) "def"
// ["max_length"]=>
// int(3)
// ["length"]=>
// int(765)
// ["charsetnr"]=>
// int(33)
// ["flags"]=>
// int(0)
// ["type"]=>
// int(253)
// ["decimals"]=>
// int(0)
// }

fetch_fields() 方法和 fetch_all() 是类似的,它就是获取全部的字段信息。而 fetch_field_direct() 则是根据参数来获取指定下标的字段信息。

总结

至此,MySQLi 相关扩展的学习我们也就告一段落了,其它的一些类和函数比如 MySQLI_Driver 、 MySQLI_Exception 之类的内容大家可以自行查阅相关的文档,内容都不是很多。MySQLI_Driver 对象可以帮助我们指定当前驱动的报错形式,之前的文章中我们也已经接触过。

总体来说,整个 PHP 中和 MySQL 打交道的官方扩展我们就已经全部学习完了,PDO 和 MYSQLi 这两个扩展大家更主要的还是要掌握它们的区别和联系。在实际的业务开发中 PDO 还是会使用得更多,但 MySQLi 也绝不是能够完全忽略的,多多动手尝试学习吧。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202009/source/9.PHP中的MySQLi扩展学习(六)MySQLI_result对象操作.php

参考文档:

https://www.php.net/manual/zh/class.mysqli-result.php

PHP中的MySQLi扩展学习(六)MySQLI_result对象操作的更多相关文章

  1. PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作

    就像 PDO 中的 PDO_Statment 对象一样,MySQLI_STMT 对象也是一个预处理语句所形成的对象,专门用来操作 MySQLi 所生成的预处理语句的.其实操作方式之类也都比较相似,不外 ...

  2. PHP中的MySQLi扩展学习(四)mysqli的事务与预处理语句

    对于 MySQLi 来说,事务和预处理语句当然是它之所以能够淘汰 MySQL(原始) 扩展的资本.我们之前也已经学习过了 PDO 中关于事务和预处理语句相关的内容.所以在这里,我们就不再多讲理论方面的 ...

  3. PHP中的MySQLi扩展学习(三)mysqli的基本操作

    我们继续 MySQLi 扩展的学习,上篇文章中提到过,MySQLi 的扩展相对于 PDO 来说功能更加的丰富,所以我们依然还会在学习过程中穿插各种 MySQLi 中好玩的方法函数.不过,今天的主角是 ...

  4. PHP中的MySQLi扩展学习(二)mysqli类的一些少见的属性方法

    虽说是少见的一些属性方法,但是可能还是有不少同学在日常的开发中使用过,这里只是学习了可能相对来说我们用得比较少的一些 mysqli 的属性或方法.就当是扩展一下自己的知识体系. 切换用户 首先就是切换 ...

  5. PHP中的MySQLi扩展学习(一)MySQLi介绍

    关于 PDO 的学习我们告一段落,从这篇文章开始,我们继续学习另外一个 MySQL 扩展,也就是除了 PDO 之外的最核心的 MySQLi 扩展.可以说它的祖先,也就是 MySQL(原始) 扩展是我们 ...

  6. C#多线程学习(六) 互斥对象

    如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类. 我们可以把Mutex看作一个出租车,乘客看作线程.乘客首先 ...

  7. Scala学习(六)---Scala对象

    Scala中的对象 摘要: 在本篇中,你将会学到何时使用Scala的object语法结构.在你需要某个类的单个实例时,或者想为其他值或函数找一个可以挂靠的地方时,你就会用到它.本篇的要点包括: 1. ...

  8. 解决phpMyAdmin中缺少mysqli扩展的错误

  9. phpmyadmin中缺少mysqli扩展 的结解办法

    修改 ;extension=php_mysqli.dll  去掉前面的 ;     以及 调整 php文件夹的目录位置.     这个办法是不是好使,我不确定.这个方法只适合 用win系统 这个,貌似 ...

随机推荐

  1. RadioButton 自定义样式(带动画)

    <Style x:Key="Radbtn" TargetType="{x:Type RadioButton}"> <Setter Proper ...

  2. 课程设计-基于SSM的美容美发造型预约管理系统代码Java理发剪发设计造型系统vue美发店管理系统

    注意:该项目只展示部分功能,如需了解,评论区咨询即可. 1.开发环境 开发语言:Java 后台框架:SSM 前端框架:vue 数据库:MySQL 设计模式:MVC 架构:B/S 源码类型: Web 编 ...

  3. 阿里云NAS文件迁移项目实践

    阿里云文件存储NAS是阿里云推出的用于传统文件共享的,使用NFS协议挂载的共享文件夹. 产品背景 下图是NAS和阿里云另一明星产品OSS以及块存储EBS的区别 NAS核心优势:无需修改程序,挂载之后, ...

  4. NOIP 模拟 $27\; \rm 牛半仙的妹子Tree$

    题解 \(by\;zj\varphi\) 很妙的虚树题. 考虑若没有操作 \(2\),那么直接记录一下扩散到它的最短时间和询问时间相比即可,可以当作一个树上最短路. 有 \(2\) 操作怎么办,将操作 ...

  5. SpringCloud商品服务调用方式之Ribbon

    1.创建order_service项目 pom依赖 <dependency> <groupId>org.springframework.boot</groupId> ...

  6. transient用法

    1 import java.io.FileInputStream; 2 import java.io.FileNotFoundException; 3 import java.io.FileOutpu ...

  7. NIO中的File

    package nio; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files ...

  8. 原生 JS 与 jQuery 中的 AJAX

    AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更 ...

  9. Go定时器--Timer

    目录 前言 Timer 定时器 简介 使用场景 1. 设定超时时间 2. 延迟执行某个方法 Timer对外接口 1. 创建定时器 2. 停止定时器 3. 重置定时器 其他接口 1. After() 2 ...

  10. roscore启动不完全问题

    运行roscore,得到如下日志,且一直卡着无法继续执行 ... logging to /home/xbit/.ros/log/79f2952c-589c-11ea-8213-d0abd5e7d222 ...