È possibile riavvolgere un risultato DOP?
Domanda
Sto cercando di scrivere un iteratore per i risultati di un'istruzione PDO ma non riesco a trovare alcun modo per riavvolgere la prima riga. Vorrei evitare il sovraccarico di chiamare fetchAll e archiviare tutti i dati dei risultati.
// first loop works fine
foreach($statement as $result) {
// do something with result
}
// but subsequent loops don't
foreach($statement as $result) {
// never called
}
Esiste un modo per ripristinare la dichiarazione o cercare la prima riga?
Soluzione
Sono abbastanza sicuro che questo dipende dal database. Per questo motivo, è qualcosa che dovresti cercare di evitare. Tuttavia, penso che puoi ottenere ciò che desideri abilitando query bufferizzate . Se ciò non funziona, puoi sempre inserire il risultato in un array con
Altri suggerimenti
Questa piccola classe che ho scritto avvolge un PDOStatement. Memorizza solo i dati recuperati. Se non funziona, puoi spostare la cache per leggere e scrivere in un file.
// Wrap a PDOStatement to iterate through all result rows. Uses a
// local cache to allow rewinding.
class PDOStatementIterator implements Iterator
{
public
$stmt,
$cache,
$next;
public function __construct($stmt)
{
$this->cache = array();
$this->stmt = $stmt;
}
public function rewind()
{
reset($this->cache);
$this->next();
}
public function valid()
{
return (FALSE !== $this->next);
}
public function current()
{
return $this->next[1];
}
public function key()
{
return $this->next[0];
}
public function next()
{
// Try to get the next element in our data cache.
$this->next = each($this->cache);
// Past the end of the data cache
if (FALSE === $this->next)
{
// Fetch the next row of data
$row = $this->stmt->fetch(PDO::FETCH_ASSOC);
// Fetch successful
if ($row)
{
// Add row to data cache
$this->cache[] = $row;
}
$this->next = each($this->cache);
}
}
}
vedi slide 31 di questa presentazione , puoi fare una < code> $ statement- > rewind () se si applica a una query con buffer. Se si utilizza mysql, è possibile emulare query con buffer utilizzando PDO_MYSQL_ATTR_USE_BUFFERED_QUERY
:
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
@NoahGoodrich ti ha indicato di dividere. Ecco un esempio che funziona sempre:
$it = new ArrayIterator($stmt->fetchAll());
Probabilmente vorrai dare un'occhiata ad alcune delle classi PHP SPL che possono essere estese per fornire un accesso simile agli array agli oggetti.
- Standard PHP Library (SPL) Vorrei specificamente ti consiglio di guardare il ArrayIterator, ArrayObject e forse l'interfaccia Iterator.
- Semplice Tutorial
- Un altro Tutorial rapido
Chiesto molto tempo fa ma al momento esiste un'altra soluzione.
Il metodo PDOStatement :: fetch ()
può ricevere un secondo parametro, l'orientamento del cursore, con una delle costanti PDO :: FETCH_ORI_ *
. Questi parametri sono validi solo se PDOStatement
vengono creati con l'attributo PDO :: ATTR_CURSOR
come PDO :: CURSOR_SCROLL
.
In questo modo puoi navigare come segue.
$sql = "Select * From Tabela";
$statement = $db->prepare($sql, array(
PDO::ATTR_CURSOR => PDO::CURSOR_SCROLL,
));
$statement->execute();
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_NEXT); // return next
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_PRIOR); // return previous
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_FIRST); // return first
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_LAST); // return last
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $n); // return to $n position
$statement->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_REL, $n); // return to $n position relative to current
Ulteriori informazioni in docs e < a href = "http://php.net/manual/en/pdo.constants.php" rel = "nofollow"> costanti predefinite DOP .
Nota: usato PDO :: FETCH_BOTH
perché è l'impostazione predefinita, basta personalizzarlo per il proprio progetto.