# 生成查询结果

生成查询结果的方式有多种：

## 结果数组

### getResult()

此方法将查询结果以 对象数组 形式返回，失败时则返回 空数组。

#### 获取 stdClass 数组

通常你会在 foreach 循环中使用它，如下所示：

    <?php

    $query = $db->query('YOUR QUERY');

    foreach ($query->getResult() as $row) {
        echo $row->title;
        echo $row->name;
        echo $row->body;
    }

上述方法是 `CodeIgniter\Database\BaseResult::getResultObject()` 的别名。

#### 获取数组的数组

如果希望结果以数组的数组形式返回，可以传入字符串 'array'：

    <?php

    $query = $db->query('YOUR QUERY');

    foreach ($query->getResult('array') as $row) {
        echo $row['title'];
        echo $row['name'];
        echo $row['body'];
    }

上述用法是 getResultArray() 的别名。

#### 获取自定义对象数组

也可以向 `getResult()` 传递一个字符串，表示为每个结果对象实例化的类名

    <?php

    $query = $db->query('SELECT * FROM users;');

    foreach ($query->getResult(\App\Entities\User::class) as $user) {
        echo $user->name;          // access attributes
        echo $user->reverseName(); // or methods defined on the 'User' class
    }

上述方法是 getCustomResultObject() 的别名。

### getResultArray()

此方法将查询结果作为纯数组返回，如果没有产生结果则返回空数组。通常你会在 foreach 循环中使用它，如下所示：

    <?php

    $query = $db->query('YOUR QUERY');

    foreach ($query->getResultArray() as $row) {
        echo $row['title'];
        echo $row['name'];
        echo $row['body'];
    }

## 结果集

### getRow()

此方法返回单个结果集。如果查询有多行，它只返回第一行。结果以 对象 形式返回。用法示例：

    <?php

    $query = $db->query('YOUR QUERY');

    $row = $query->getRow();

    if (isset($row)) {
        echo $row->title;
        echo $row->name;
        echo $row->body;
    }

如果需要返回特定行，可以在第一个参数中提交行号（数字）：

    <?php

    $row = $query->getRow(5);

还可以添加第二个字符串参数，指定用于实例化行的类名：

    <?php

    $query = $db->query('SELECT * FROM users LIMIT 1;');
    $row   = $query->getRow(0, \App\Entities\User::class);

    echo $row->name;           // access attributes
    echo $row->reverse_name(); // or methods defined on the 'User' class

### getRowArray()

与上面的 `row()` 方法相同，只是它返回数组。示例：

    <?php

    $query = $db->query('YOUR QUERY');

    $row = $query->getRowArray();

    if (isset($row)) {
        echo $row['title'];
        echo $row['name'];
        echo $row['body'];
    }

如果需要返回特定行，可以在第一个参数中提交行号（数字）：

    <?php

    $row = $query->getRowArray(5);

此外，可以使用以下变体在结果中前进/后退/定位到第一行/最后一行：

> `$row = $query->getFirstRow()`
> `$row = $query->getLastRow()`
> `$row = $query->getNextRow()`
> `$row = $query->getPreviousRow()`

默认情况下它们返回对象，除非在参数中放入 "array" 单词：

> `$row = $query->getFirstRow('array')`
> `$row = $query->getLastRow('array')`
> `$row = $query->getNextRow('array')`
> `$row = $query->getPreviousRow('array')`

备注

上述所有方法都会将整个结果加载到内存中（预取）。处理大型结果集时使用 `getUnbufferedRow()`。

### getUnbufferedRow()

此方法返回单个结果集，不像 `row()` 那样将整个结果预取到内存中。如果查询有多行，它会返回当前行并将内部数据指针向前移动。

    <?php

    $query = $db->query('YOUR QUERY');

    while ($row = $query->getUnbufferedRow()) {
        echo $row->title;
        echo $row->name;
        echo $row->body;
    }

对于 MySQLi，可以将 MySQLi 的结果模式设置为 `MYSQLI_USE_RESULT` 以最大化内存节省。一般不推荐使用此设置，但在某些情况下（如将大型查询写入 CSV）可能有益。更改结果模式时请注意相关的权衡。

    <?php

    $db->resultMode = MYSQLI_USE_RESULT; // for unbuffered results

    $query = $db->query('YOUR QUERY');

    $file = new \CodeIgniter\Files\File(WRITEPATH . 'data.csv');

    $csv = $file->openFile('w');

    while ($row = $query->getUnbufferedRow('array')) {
        $csv->fputcsv($row);
    }

    $db->resultMode = MYSQLI_STORE_RESULT; // return to default mode

备注

使用 `MYSQLI_USE_RESULT` 时，在获取所有记录或调用 `freeResult()` 之前，对同一连接的所有后续调用都会导致错误。`getNumRows()` 方法只会根据数据指针的当前位置返回行数。MyISAM 表将保持锁定状态，直到获取所有记录或调用 `freeResult()`。

可以选择性地传递 'object'（默认）或 'array' 来指定返回值的类型：

    <?php

    $query->getUnbufferedRow();         // object
    $query->getUnbufferedRow('object'); // object
    $query->getUnbufferedRow('array');  // associative array

## 自定义结果对象

可以让结果返回为自定义类的实例，而不是 `stdClass` 或数组，就像 `getResult()` 和 `getResultArray()` 方法允许的那样。如果类尚未加载到内存中，自动加载器将尝试加载它。对象将把数据库返回的所有值设置为属性。如果这些属性已声明且是非公共的，则应提供 `__set()` 方法以允许设置它们。

示例：

    <?php

    namespace App\Entities;

    class User
    {
        public $id;
        public $email;
        public $username;

        protected $lastLogin;

        public function lastLogin($format)
        {
            return $this->lastLogin->format($format);
        }

        public function __set($name, $value)
        {
            if ($name === 'lastLogin') {
                $this->lastLogin = DateTime::createFromFormat('!U', $value);
            }
        }

        public function __get($name)
        {
            if (isset($this->{$name})) {
                return $this->{$name};
            }
        }
    }

除了下面列出的两个方法外，以下方法也可以接受类名以返回结果：`getFirstRow()`、`getLastRow()`、`getNextRow()` 和 `getPreviousRow()`。

### getCustomResultObject()

将整个结果集返回为请求的类实例的数组。唯一的参数是要实例化的类名。

示例：

    <?php

    $query = $db->query('YOUR QUERY');

    $rows = $query->getCustomResultObject(\App\Entities\User::class);

    foreach ($rows as $row) {
        echo $row->id;
        echo $row->email;
        echo $row->lastLogin('Y-m-d');
    }

### getCustomRowObject()

从查询结果中返回单行。第一个参数是结果的行号。第二个参数是要实例化的类名。

示例：

    <?php

    $query = $db->query('YOUR QUERY');

    $row = $query->getCustomRowObject(0, \App\Entities\User::class);

    if (isset($row)) {
        echo $row->email;              // access attributes
        echo $row->lastLogin('Y-m-d'); // access class methods
    }

也可以以完全相同的方式使用 `getRow()` 方法。

示例：

    <?php

    $row = $query->getRow(0, \App\Entities\User::class);

## 结果辅助方法

### getFieldCount()

查询返回的字段（列）数量。确保使用查询结果对象调用此方法：

    <?php

    $query = $db->query('SELECT * FROM my_table');

    echo $query->getFieldCount();

### getFieldNames()

返回包含查询返回的字段（列）名称的数组。确保使用查询结果对象调用此方法：

    <?php

    $query = $db->query('SELECT * FROM my_table');

    echo $query->getFieldNames();

### getNumRows()

查询返回的记录数。确保使用查询结果对象调用此方法：

    <?php

    $query = $db->query('SELECT * FROM my_table');

    echo $query->getNumRows();

备注

由于 SQLite3 缺乏高效的返回记录计数的方法，CodeIgniter 会在内部获取并缓冲查询结果记录，然后返回结果记录数组的计数，这可能效率不高。

### freeResult()

释放与结果关联的内存并删除结果资源 ID。通常 PHP 会在脚本执行结束时自动释放内存。但是，如果在特定脚本中运行大量查询，可能希望在生成每个查询结果后释放结果，以减少内存消耗。

示例：

    <?php

    $query = $thisdb->query('SELECT title FROM my_table');

    foreach ($query->getResult() as $row) {
        echo $row->title;
    }

    $query->freeResult(); // The $query result object will no longer be available

    $query2 = $db->query('SELECT name FROM some_table');

    $row = $query2->getRow();
    echo $row->name;
    $query2->freeResult(); // The $query2 result object will no longer be available

### dataSeek()

此方法设置下一个要获取的结果集的内部指针。它仅在与 `getUnbufferedRow()` 结合使用时有用。

它接受一个正整数值（默认为 0），成功时返回 true，失败时返回 false。

    <?php

    $query = $db->query('SELECT `field_name` FROM `table_name`');
    $query->dataSeek(5); // Skip the first 5 rows
    $row = $query->getUnbufferedRow();

备注

并非所有数据库驱动程序都支持此功能，不支持的驱动程序将返回 false。最明显的是，无法在 PDO 中使用此功能。

## 类参考

class CodeIgniter\Database\BaseResult
  getResult([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      包含获取行的数组

    返回类型:

      `array`

    `getResultArray()`、`getResultObject()` 和 `getCustomResultObject()` 方法的包装器。

    用法：参见 结果数组。

  getResultArray()
    返回:

      包含获取行的数组

    返回类型:

      `array`

    将查询结果返回为行的数组，其中每行本身是一个关联数组。

    用法：参见 结果数组。

  getResultObject()
    返回:

      包含获取行的数组

    返回类型:

      `array`

    将查询结果返回为行的数组，其中每行是 `stdClass` 类型的对象。

    用法：参见 获取 stdClass 数组。

  getCustomResultObject($className)
    参数:

      - $className (`string`) -- 结果集的类名

    返回:

      包含获取行的数组

    返回类型:

      `array`

    将查询结果返回为行的数组，其中每行是指定类的实例。

  getRow([$n = 0[, $type = 'object']])
    参数:

      - $n (`int`) -- 要返回的查询结果集索引

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      请求的行，如果不存在则为 null

    返回类型:

      `mixed`

    `getRowArray()`、`getRowObject()` 和 `getCustomRowObject()` 方法的包装器。

    用法：参见 结果集。

  getUnbufferedRow([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      结果集中的下一行，如果不存在则为 null

    返回类型:

      `mixed`

    获取下一个结果集并以请求的形式返回。

    用法：参见 结果集。

  getRowArray([$n = 0])
    参数:

      - $n (`int`) -- 要返回的查询结果集索引

    返回:

      请求的行，如果不存在则为 null

    返回类型:

      `array`

    将请求的结果集返回为关联数组。

    用法：参见 结果集。

  getRowObject([$n = 0])
    参数:

      - $n (`int`) -- 要返回的查询结果集索引 :returns: 请求的行，如果不存在则为 null

    返回类型:

      `stdClass`

    将请求的结果集返回为 `stdClass` 类型的对象。

    用法：参见 结果集。

  getCustomRowObject($n, $type)
    参数:

      - $n (`int`) -- 要返回的结果集索引

      - $class_name (`string`) -- 结果集的类名

    返回:

      请求的行，如果不存在则为 null

    返回类型:

      `$type`

    将请求的结果集返回为请求类的实例。

  dataSeek([$n = 0])
    参数:

      - $n (`int`) -- 下一个要返回的结果集索引

    返回:

      成功时为 true，失败时为 false

    返回类型:

      `bool`

    将内部结果集指针移动到所需的偏移量。

    用法：参见 结果辅助方法。

  setRow($key[, $value = null])
    参数:

      - $key (`mixed`) -- 列名或键/值对数组

      - $value (`mixed`) -- 分配给列的值，当 $key 是单个字段名时

    返回类型:

      `void`

    为特定列分配值。

  getNextRow([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      结果集的下一行，如果不存在则为 null

    返回类型:

      `mixed`

    返回结果集中的下一行。

  getPreviousRow([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      结果集的上一行，如果不存在则为 null

    返回类型:

      `mixed`

    返回结果集中的上一行。

  getFirstRow([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      结果集的第一行，如果不存在则为 null

    返回类型:

      `mixed`

    返回结果集中的第一行。

  getLastRow([$type = 'object'])
    参数:

      - $type (`string`) -- 请求的结果类型 - array、object 或类名

    返回:

      结果集的最后一行，如果不存在则为 null

    返回类型:

      `mixed`

    返回结果集中的最后一行。

  getFieldCount()
    返回:

      结果集中的字段数

    返回类型:

      `int`

    返回结果集中的字段数。

    用法：参见 结果辅助方法。

  getFieldNames()
    返回:

      列名数组

    返回类型:

      `array`

    返回包含结果集中字段名的数组。

  getFieldData()
    返回:

      包含字段元数据的数组

    返回类型:

      `array`

    生成包含字段元数据的 `stdClass` 对象数组。

  getNumRows()
    返回:

      结果集中的行数

    返回类型:

      `int`

    返回查询返回的行数

  freeResult()
    返回类型:

      `void`

    释放结果集。

    用法：参见 结果辅助方法。