Ist es möglich, ein PDO Ergebnis zurückspulen?
Frage
Ich versuche, einen Iterator für die Ergebnisse einer PDO-Anweisung zu schreiben, aber ich kann nicht jede mögliche Weise von Zurückspulen in der ersten Reihe finden. Ich möchte den Aufwand der Aufruf fetchAll vermeiden und alle Ergebnisdaten zu speichern.
// first loop works fine
foreach($statement as $result) {
// do something with result
}
// but subsequent loops don't
foreach($statement as $result) {
// never called
}
Gibt es eine Möglichkeit, die Mitteilung des Reseting oder die erste Zeile suchen?
Lösung
Ich bin mir ziemlich sicher, dass dies die Datenbank abhängig ist. Aus diesem Grund ist es etwas, das Sie versuchen sollten, zu vermeiden. Aber ich denke, können Sie erreichen, was Sie wollen von gepuffert Abfragen ermöglicht. Wenn das nicht funktioniert, können Sie immer das Ergebnis in einem Array ziehen mit fetchAll
. Beide Lösungen haben Auswirkungen auf Ihre Anwendungen Leistung, so denken Sie zweimal darüber nach, wenn die Result groß sind.
Andere Tipps
Diese kleine Klasse schrieb ich wickelt eine PDOStatement. Es speichert nur die Daten, die abgerufen werden. Wenn dies nicht funktioniert, können Sie den Cache bewegen, um eine Datei zu lesen und zu schreiben.
// 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);
}
}
}
finden Sie unter 31 gleiten aus dieser Präsentation , können Sie eine $statement->rewind()
tun wenn es gilt für eine gepufferte Abfrage. Wenn Sie MySQL verwenden, können Sie gepufferte Abfragen emulieren, indem PDO_MYSQL_ATTR_USE_BUFFERED_QUERY
mit:
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1);
@NoahGoodrich wies Sie spl. Hier ist ein Beispiel, das immer funktioniert:
$it = new ArrayIterator($stmt->fetchAll());
Sie werden wahrscheinlich wollen einen Blick auf einige der PHP SPL Klassen nehmen, die erweitert werden kann Array-ähnlichen Zugriff auf Objekte zu schaffen.
- Standard PHP Library (SPL) würde ich speziell wird empfohlen, die zu buchen ArrayIterator, Arrayobject, und vielleicht die Iterator-Schnittstelle.
- Einfache Tutorial
- Ein weiterer Quick-Tutorial
vor langer Zeit gefragt, aber derzeit gibt es eine andere Lösung.
Die Methode PDOStatement::fetch()
kann einen zweiten Parameter, um die Cursor Ausrichtung, mit einem von PDO::FETCH_ORI_*
Konstanten erhält. Diese Parameter sind nur gültig, wenn der PDOStatement
mit dem atribute PDO::ATTR_CURSOR
als PDO::CURSOR_SCROLL
erstellt werden.
So können Sie wie folgt navigieren können.
$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
Weitere Informationen unter docs und < a href = "http://php.net/manual/en/pdo.constants.php" rel = "nofollow"> PDO vordefinierte Konstanten .
Hinweis: verwendet PDO::FETCH_BOTH
weil der Standard ist, passen Sie es nur für Ihr Projekt