W3docs

data_seek

Узнайте, как функция mysqli_data_seek() в PHP перемещает внутренний указатель буферизованного результата к произвольной строке.

Функция mysqli_data_seek() в PHP перемещает внутренний указатель результата к произвольной строке в буферизованном наборе результатов, так что следующий вызов выборки читает именно эту строку, а не следующую по порядку. Она позволяет перейти прямо к нужной строке, перечитать уже пройденные строки или начать сначала без повторного выполнения запроса. Индексы строк начинаются с нуля, а функция возвращает true при успехе или false при ошибке.

В этой главе рассматриваются сигнатура функции, процедурный и объектно-ориентированный стили, рабочий пример, требование к буферизованному результату, которое чаще всего вызывает затруднения, а также случаи, когда SQL-конструкция LIMIT … OFFSET является более подходящим инструментом.

Синтаксис

// Procedural style
mysqli_data_seek(mysqli_result $result, int $offset): bool

// Object-oriented style
$result->data_seek(int $offset): bool
  • $result — набор результатов, возвращённый функцией mysqli_query(), mysqli_store_result() или mysqli_use_result().
  • $offset — номер строки, к которой нужно перейти; отсчёт начинается с 0 для первой строки. Значение должно быть в диапазоне от 0 до mysqli_num_rows() - 1.
  • Возвращаемое значениеtrue, если переход выполнен успешно, или false, если смещение выходит за пределы диапазона либо набор результатов не буферизован.

Требование к буферизованному результату

mysqli_data_seek() работает только с буферизованными наборами результатов — теми, строки которых уже хранятся в памяти. Именно такой результат возвращает mysqli_query() (которая внутренне вызывает mysqli_store_result()) и непосредственно mysqli_store_result().

Если вы получаете строки в ленивом режиме с помощью mysqli_use_result(), строки передаются с сервера по одной, и перемещаться по ним нельзя, поэтому mysqli_data_seek() завершится ошибкой. Когда нужен произвольный доступ, используйте буферизованный результат.

Как использовать mysqli_data_seek()

Вызовите функцию для действительного набора результатов и передайте индекс нужной строки. Следующая выборка вернёт именно эту строку:

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

$result = mysqli_query($mysqli, "SELECT id, name FROM users ORDER BY id");

if (!$result) {
    echo "Failed to execute query: " . mysqli_error($mysqli);
    exit();
}

// Move the pointer to row 3 (index 2, because indices are zero-based)
if (!mysqli_data_seek($result, 2)) {
    echo "Seek failed";
    exit();
}

// Fetch the row the pointer now points at
$row = mysqli_fetch_assoc($result);

print_r($row);

mysqli_free_result($result);
mysqli_close($mysqli);
?>

Мы подключаемся с помощью mysqli_connect(), выполняем запрос через mysqli_query() и проверяем наличие ошибок. Затем mysqli_data_seek($result, 2) перемещает указатель к третьей строке, а mysqli_fetch_assoc() её читает. Проверка возвращаемого значения mysqli_data_seek() позволяет корректно обработать выход смещения за допустимый диапазон.

Повторное чтение набора результатов с начала

Удобный способ без обращения к базе данных — чтобы понять, как ведёт себя указатель, — пройти по результату, затем вернуться к 0 и пройти ещё раз. Следующий фрагмент использует обычный PHP array для моделирования той же логики выборки и перемещения без реального сервера MySQL:

<?php
// A result set modelled as an in-memory array of rows.
$rows = [
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
    ['id' => 3, 'name' => 'Carol'],
];

$pointer = 0;

// "data_seek": move the pointer to an arbitrary index, like mysqli_data_seek().
function data_seek(array $rows, int $offset, int &$pointer): bool
{
    if ($offset < 0 || $offset >= count($rows)) {
        return false;
    }
    $pointer = $offset;
    return true;
}

// First pass: read every row sequentially.
echo "First pass:\n";
while ($pointer < count($rows)) {
    echo $rows[$pointer]['name'] . "\n";
    $pointer++;
}

// Rewind to the top and read again.
data_seek($rows, 0, $pointer);

echo "Second pass (after seek to 0):\n";
echo $rows[$pointer]['name'] . "\n"; // Alice again
?>

Вывод программы:

First pass:
Alice
Bob
Carol
Second pass (after seek to 0):
Alice

При работе с реальным mysqli_result вместо логики с array нужно использовать mysqli_data_seek($result, 0) с последующим вызовом mysqli_fetch_assoc($result), чтобы перемотать буферизованный результат без повторного выполнения запроса.

Когда лучше использовать LIMIT/OFFSET

mysqli_data_seek() предназначена для навигации по набору результатов, который вы уже загрузили. Если цель — получить только часть большой таблицы, не нужно тащить все строки в PHP ради перемещения — передайте работу базе данных с помощью LIMIT и OFFSET:

SELECT id, name FROM users ORDER BY id LIMIT 10 OFFSET 20;

Это вернёт только 10 нужных строк, экономя память и сетевой трафик. Оставляйте mysqli_data_seek() для случаев, когда действительно необходим произвольный доступ к набору результатов, уже находящемуся в памяти, — например, для повторного чтения более ранних строк в рамках одного запроса.

Заключение

mysqli_data_seek() перемещает внутренний указатель буферизованного набора результатов, позволяя перейти к любой строке с нулевым индексом, включая возврат к началу. Помните о двух ограничениях: смещение должно быть в допустимом диапазоне (0num_rows - 1), а набор результатов — быть буферизованным. Для ограничения больших наборов данных предпочтительнее SQL-конструкция LIMIT/OFFSET; для навигации по данным, уже находящимся в памяти, mysqli_data_seek() — правильный инструмент.

Связанные функции: mysqli_fetch_assoc(), mysqli_fetch_array(), mysqli_fetch_row() и mysqli_query().

Практика

Практика
Каково основное назначение метода PHP mysql_data_seek()?
Каково основное назначение метода PHP mysql_data_seek()?
Was this page helpful?