data_seek
Scopri come usare mysqli_data_seek() in PHP per spostare il puntatore del risultato a una riga specifica in un result set bufferizzato.
La funzione mysqli_data_seek() in PHP sposta il puntatore interno del risultato a una riga arbitraria in un result set bufferizzato, così la successiva chiamata di fetch leggerà da quella riga anziché dalla successiva in sequenza. Permette di saltare direttamente a una riga, rileggere righe già passate o ricominciare dall'inizio senza eseguire nuovamente la query. Gli indici di riga sono a base zero e la funzione restituisce true in caso di successo o false in caso di errore.
Questo capitolo tratta la firma della funzione, gli stili procedurale e orientato agli oggetti, un esempio eseguibile, il requisito del result set bufferizzato che crea problemi alla maggior parte delle persone, e quando SQL LIMIT … OFFSET è lo strumento migliore.
Sintassi
// Procedural style
mysqli_data_seek(mysqli_result $result, int $offset): bool
// Object-oriented style
$result->data_seek(int $offset): bool$result— un result set restituito damysqli_query(),mysqli_store_result()omysqli_use_result().$offset— il numero di riga su cui spostarsi, a partire da0per la prima riga. Deve essere compreso tra0emysqli_num_rows() - 1.- Valore restituito —
truese lo spostamento ha successo,falsese l'offset è fuori intervallo o il result set non è bufferizzato.
Il requisito del result set bufferizzato
mysqli_data_seek() funziona solo con result set bufferizzati — quelli le cui righe sono già tenute in memoria. Questo è ciò che si ottiene da mysqli_query() (che chiama mysqli_store_result() internamente) e da mysqli_store_result() direttamente.
Se si recuperano le righe in modo pigro con mysqli_use_result(), le righe vengono trasmesse dal server una alla volta e non c'è nulla su cui eseguire lo spostamento, quindi mysqli_data_seek() fallirà. Quando si necessita di accesso casuale, è necessario utilizzare un result set bufferizzato.
Come usare mysqli_data_seek()
Chiama la funzione su un result set valido e passa l'indice di riga su cui vuoi posizionarti. Il fetch successivo restituirà quella riga:
<?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);
?>Ci connettiamo con mysqli_connect(), eseguiamo la query con mysqli_query() e controlliamo gli errori. Poi mysqli_data_seek($result, 2) sposta il puntatore alla terza riga, e mysqli_fetch_assoc() la legge. Controllare il valore restituito da mysqli_data_seek() consente di gestire in modo pulito un offset fuori intervallo.
Rileggere un result set dall'inizio
Un modo comune, senza database, per vedere esattamente come si comporta il puntatore è scorrere un result set, poi tornare a 0 e scorrere di nuovo. Questo frammento usa un semplice array PHP per simulare la stessa logica di fetch-poi-seek senza la necessità di un server MySQL attivo:
<?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
?>Questo stampa:
First pass:
Alice
Bob
Carol
Second pass (after seek to 0):
AliceCon un vero mysqli_result, si sostituirebbe la logica dell'array con mysqli_data_seek($result, 0) seguito da mysqli_fetch_assoc($result) per riavvolgere un result set bufferizzato senza rieseguire la query.
Quando usare LIMIT/OFFSET invece
mysqli_data_seek() serve a navigare in un result set che si è già scaricato. Se l'obiettivo è recuperare solo una porzione di una tabella grande, non portare tutte le righe in PHP solo per fare uno spostamento — delega il lavoro al database con LIMIT e OFFSET:
SELECT id, name FROM users ORDER BY id LIMIT 10 OFFSET 20;Questo restituisce solo le 10 righe desiderate, risparmiando memoria e traffico di rete. Riserva mysqli_data_seek() per i casi in cui hai genuinamente bisogno di accesso casuale su un result set già in memoria — ad esempio, rileggere righe precedenti durante una singola richiesta.
Conclusione
mysqli_data_seek() riposiziona il puntatore interno di un result set bufferizzato in modo da poter saltare a qualsiasi riga a base zero, compreso il ritorno all'inizio. Ricorda i suoi due vincoli: l'offset deve essere nell'intervallo (0 … num_rows - 1) e il result set deve essere bufferizzato. Per ridurre dataset di grandi dimensioni, preferisci SQL LIMIT/OFFSET; per spostarti tra dati già in memoria, mysqli_data_seek() è lo strumento giusto.
Funzioni correlate: mysqli_fetch_assoc(), mysqli_fetch_array(), mysqli_fetch_row() e mysqli_query().