Получение строк и метаданных через mysqli_fetch: практическое руководство

Раздел: Веб-разработка на PHP -> Работа с базами данных в PHP

Основные способы извлечения данных из результата запроса

Наиболее эффективное решение для обработки результата запроса mysqli - использование функции mysqli_fetch_assoc в цикле while. Этот метод позволяет построчно читать данные, не загружая их все в память, и подходит для любых объёмов выборки.


$result = $mysqli->query("SELECT id, name, email FROM users");
while ($row = $result->fetch_assoc()) {
    echo $row['id'] . ' - ' . $row['name'] . '<br>';
}
$result->free();

Pdo php 8 (pdo в php 8)

Каждый вызов fetch_assoc возвращает ассоциативный массив с ключами, соответствующими названиям столбцов. Когда строки заканчиваются, возвращается null и цикл завершается. Для небольшого набора данных можно использовать fetch_all, который сразу возвращает двумерный массив всех строк.


$rows = $result->fetch_all(MYSQLI_ASSOC);
foreach ($rows as $row) {
    echo $row['name'] . '<br>';
}

Php pdo pgsql (pdo для postgresql)

Примечание:

При работе с большими объёмами данных (например, более 10 000 строк) fetch_all потребляет много памяти, поэтому цикл с fetch_assoc предпочтительнее.

Как получить ассоциативный массив с именами столбцов?

Используется mysqli_fetch_assoc (или метод fetch_assoc у объекта результата). Функция возвращает массив вида ['column' => value] или null, если строк больше нет.


$row = $result->fetch_assoc();
echo $row['name'];

Php pdo query (выполнение запросов pdo)

Типичная ошибка: не проверять, вернула ли функция false (на самом деле null в случае отсутствия строк). В цикле while это обрабатывается автоматически, но если вызывать без цикла, нужно проверять:


if ($row = $result->fetch_assoc()) {
    // есть данные
} else {
    // строк нет или ошибка
}

Php pdo error (ошибки pdo)

Как получить нумерованный массив (без названий столбцов)?

Функция mysqli_fetch_row возвращает обычный массив с индексами от 0.


$row = $result->fetch_row();
echo $row[0] . ' - ' . $row[1];

Index php pdo (index.php с pdo)

Если вы измените порядок столбцов в запросе, индексы в массиве также изменятся, что может привести к ошибкам при чтении данных.

Как получить одновременно и ассоциативный, и нумерованный массив?

Функция mysqli_fetch_array с константой MYSQLI_BOTH (по умолчанию) возвращает массив, где каждый элемент доступен и по имени столбца, и по индексу.


$row = $result->fetch_array(MYSQLI_BOTH);
echo $row['name'] . ' ' . $row[0];

Db error php (ошибка базы данных в php)

Также можно использовать MYSQLI_ASSOC или MYSQLI_NUM для принудительного типа.

Двойное представление увеличивает размер массива и может замедлить работу, поэтому обычно лучше выбрать один тип.

Как получить результат в виде объекта?

Функция mysqli_fetch_object возвращает объект stdClass, где свойства соответствуют именам столбцов.


$obj = $result->fetch_object();
echo $obj->name;

Php mysqli fetch (функция mysqli_fetch в php)

Можно указать имя класса - тогда объект будет создан от этого класса (конструктор с параметрами не вызывается).


class User { public $name; }
$user = $result->fetch_object('User');
echo $user->name;

Select from users php (sql запрос select from users в php)

Если в классе объявлены приватные свойства, они не будут заполнены. Свойства должны быть публичными.

Как получить сразу все строки из результата?

mysqli_fetch_all возвращает двумерный массив всех строк. Она доступна только при установленном MySQL Native Driver (mysqlnd).


$all = $result->fetch_all(MYSQLI_ASSOC);
foreach ($all as $row) {
    print_r($row);
}

Create table php (создание таблицы в php)

Без mysqlnd функция не будет доступна - придётся использовать цикл с fetch_assoc. Также при большом количестве строк память может переполниться.

Как получить информацию о структуре полей результата?

Функция mysqli_fetch_field последовательно возвращает объекты с метаданными каждого столбца (имя, тип, длина, флаги и др.).


while ($field = $result->fetch_field()) {
    echo $field->name . ' (' . $field->type . ') ' . $field->max_length . '<br>';
}

Также существует fetch_fields (возвращает массив всех полей) и fetch_field_direct (для конкретного индекса).

При использовании fetch_field необходимо сбросить указатель с помощью field_seek, если требуется повторное чтение полей.

Расширенные примеры использования mysqli_fetch

Ниже приведены более сложные сценарии, демонстрирующие различные нюансы работы с функциями выборки.

Пакетное получение всех строк с преобразованием типов

В этом примере используется fetch_all с константой MYSQLI_ASSOC, после чего массив форматируется.

Пример

$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$result = $mysqli->query("SELECT id, name, created_at FROM logs LIMIT 5");
$rows = $result->fetch_all(MYSQLI_ASSOC);
$result->free();
echo json_encode($rows, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
[
    {
        "id": 1,
        "name": "Событие А",
        "created_at": "2023-10-01 10:00:00"
    },
    ...
]

Извлечение данных с помощью fetch_object и пользовательским классом

Создаётся класс с методом для форматирования, и все строки заполняются в экземпляры.

Пример

class Product {
    public $id;
    public $title;
    public $price;
    public function getDisplay() {
        return $this->title . ' - ' . number_format($this->price, 2) . ' руб.';
    }
}

$result = $mysqli->query("SELECT id, title, price FROM products");
$products = [];
while ($obj = $result->fetch_object('Product')) {
    $products[] = $obj;
}
foreach ($products as $p) {
    echo $p->getDisplay() . '<br>';
}
Смартфон - 29990.00 руб.
Ноутбук - 54000.00 руб.

Комбинирование fetch_assoc и prepared statements

Подготовленные запросы повышают безопасность. Результат обрабатывается как обычно.

Пример

$stmt = $mysqli->prepare("SELECT id, username FROM users WHERE status = ?");
$status = 1;
$stmt->bind_param('i', $status);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    echo $row['username'] . ' (ID: ' . $row['id'] . ')<br>';
}
$stmt->close();

Обход метаданных полей с fetch_field_direct

Получение информации о конкретном поле по индексу (нумерация с 0).

Пример

$result = $mysqli->query("SELECT id, name, email FROM users");
$field0 = $result->fetch_field_direct(0);
echo 'Первое поле: ' . $field0->name . ', тип: ' . $field0->type;
$field2 = $result->fetch_field_direct(2);
echo 'Третье поле: ' . $field2->name . ', максимальная длина: ' . $field2->max_length;
Первое поле: id, тип: 3
Третье поле: email, максимальная длина: 100

Обработка результата с большим количеством строк (ленточный режим)

Для очень больших наборов данных (например, экспорт в CSV) лучше использовать небуферизованный запрос. Однако следует помнить, что во время итерации нельзя выполнять другие запросы.

Пример

$mysqli->query("SELECT * FROM huge_table", MYSQLI_USE_RESULT);
$result = $mysqli->use_result();
while ($row = $result->fetch_assoc()) {
    fputcsv($output, $row);
}
$result->free();
$mysqli->next_result(); // если были другие запросы

Важно: при использовании MYSQLI_USE_RESULT нельзя вызывать $mysqli->query() до полного извлечения всех строк. В противном случае возникнет ошибка Commands out of sync.

Продвинутая обработка с fetch_all и группировка данных

Пример группировки строк по значению поля.

Пример

$result = $mysqli->query("SELECT category, product FROM items");
$grouped = [];
foreach ($result->fetch_all(MYSQLI_ASSOC) as $row) {
    $grouped[$row['category']][] = $row['product'];
}
print_r($grouped);
Array
(
    [Электроника] => Array
        (
            [0] => Телевизор
            [1] => Наушники
        )
    [Одежда] => Array
        (
            [0] => Футболка
        )
)

Функция mysqli_fetch в PHP - comments

En
Php mysqli fetch (php)