W3docs

next_result

В этой статье рассматривается функция mysqli_next_result() в PHP, которая используется для подготовки следующего результата mysqli_multi_query().

Когда вы отправляете несколько SQL-операторов в MySQL за один вызов с помощью mysqli_multi_query(), сервер возвращает их по одному набору результатов за раз. mysqli_next_result() — это функция, которая переводит вас с текущего набора результатов на следующий, позволяя перебрать их все. В этой статье объясняется, что возвращает функция, какие параметры принимает, какие встречаются подводные камни и как использовать её в процедурном и объектно-ориентированном стилях MySQLi.

Что делает mysqli_next_result()

mysqli_next_result() подготавливает следующий набор результатов от предыдущего вызова mysqli_multi_query() и делает его доступным для функций получения данных, таких как mysqli_store_result() или mysqli_fetch_assoc(). Внутри MySQL буферизует все наборы результатов многострочного запроса; эта функция продвигает внутренний указатель на один шаг вперёд.

Важно: один вызов mysqli_next_result() перемещает вас вперёд только на один шаг. Чтобы обработать каждый оператор, вы вызываете функцию в цикле до тех пор, пока результаты не закончатся.

Синтаксис

// Procedural style
mysqli_next_result(mysqli $mysql): bool

// Object-oriented style
$mysqli->next_result(): bool

Параметры

  • $mysql (только процедурный стиль) — объект соединения, возвращённый mysqli_connect(). В ООП-стиле это объект, на котором вызывается метод.

Возвращаемое значение

Возвращает boolean:

  • true — следующий набор результатов успешно подготовлен (или больше результатов нет и ошибки не возникло).
  • false — в следующем операторе произошла ошибка, либо предыдущий запрос не имел буферизованных результатов для перехода.

Чтобы отличить «больше результатов нет» от «следующий оператор завершился с ошибкой», используйте mysqli_more_results(): если mysqli_more_results() возвращает true, а mysqli_next_result()false, значит следующий оператор вызвал ошибку.

Как использовать mysqli_next_result() (процедурный стиль)

Выполните пакет с помощью mysqli_multi_query(), обработайте первый набор результатов, затем выполняйте цикл, пока есть ещё результаты, продвигаясь с помощью mysqli_next_result() на каждом шаге:

<?php
$mysqli = mysqli_connect("localhost", "username", "password", "database");

if (!$mysqli) {
    die("Connection failed: " . mysqli_connect_error());
}

$query  = "SELECT name FROM users LIMIT 1;";
$query .= "SELECT title FROM posts LIMIT 1;";

if (mysqli_multi_query($mysqli, $query)) {
    do {
        // mysqli_store_result() returns false for statements that
        // produce no rows (INSERT, UPDATE, DELETE), so guard with if.
        if ($result = mysqli_store_result($mysqli)) {
            while ($row = mysqli_fetch_assoc($result)) {
                print_r($row);
            }
            mysqli_free_result($result);
        }
        // Stop when there are no more results; otherwise advance.
    } while (mysqli_more_results($mysqli) && mysqli_next_result($mysqli));
} else {
    echo "Multi-query failed: " . mysqli_error($mysqli);
}

mysqli_close($mysqli);
?>

Условие do...while — ключевая идея: mysqli_more_results() проверяет, существует ли ещё один набор, а mysqli_next_result() фактически переходит к нему. Поскольку && вычисляется с коротким замыканием, mysqli_next_result() вызывается только когда следующий результат действительно существует, что позволяет избежать предупреждения, которое иначе возникло бы при вызове функции после последнего набора.

Объектно-ориентированный стиль

Та же логика с ООП API выглядит немного чище:

<?php
$mysqli = new mysqli("localhost", "username", "password", "database");

if ($mysqli->connect_errno) {
    die("Connection failed: " . $mysqli->connect_error);
}

$sql  = "SELECT name FROM users LIMIT 1;";
$sql .= "SELECT title FROM posts LIMIT 1;";

if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        }
    } while ($mysqli->more_results() && $mysqli->next_result());
}

$mysqli->close();
?>

Типичные подводные камни

  • Всегда очищайте очередь. Если вы выполняете другой запрос, пока наборы результатов от предыдущего mysqli_multi_query() ещё не обработаны, MySQLi выдаёт ошибку "Commands out of sync". Выполняйте цикл с mysqli_next_result() до тех пор, пока mysqli_more_results() не вернёт false, прежде чем выдавать новый запрос.
  • Забывать mysqli_store_result() для операторов не-SELECT. Такие операторы, как INSERT, не возвращают набор результатов, поэтому mysqli_store_result() вернёт false — это ожидаемое поведение, а не ошибка. Конструкция if ($result = ...) справляется с этим.
  • Многострочный запрос представляет риск SQL-инъекций. Передавайте в mysqli_multi_query() только доверенный SQL, контролируемый на стороне сервера. Никогда не добавляйте пользовательский ввод в многострочную строку; используйте подготовленные операторы для пользовательских данных.

Заключение

mysqli_next_result() — это функция, которая позволяет перебрать все наборы результатов, возвращённые одним вызовом mysqli_multi_query(). Используемая вместе с mysqli_more_results() внутри цикла do...while, она позволяет безопасно обрабатывать вывод каждого оператора и предотвращает рассинхронизацию соединения. Подробнее о связанном процессе читайте в mysqli_multi_query() и mysqli_fetch_assoc().

Практика

Практика
Что делает функция PHP mysqli::next_result?
Что делает функция PHP mysqli::next_result?
Was this page helpful?