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() перемещает внутренний указатель буферизованного набора результатов, позволяя перейти к любой строке с нулевым индексом, включая возврат к началу. Помните о двух ограничениях: смещение должно быть в допустимом диапазоне (0 … num_rows - 1), а набор результатов — быть буферизованным. Для ограничения больших наборов данных предпочтительнее SQL-конструкция LIMIT/OFFSET; для навигации по данным, уже находящимся в памяти, mysqli_data_seek() — правильный инструмент.
Связанные функции: mysqli_fetch_assoc(), mysqli_fetch_array(), mysqli_fetch_row() и mysqli_query().